Date: Sat, 26 Feb 2022 00:39:20 -0500
On Fri, Feb 25, 2022 at 7:28 PM organicoman via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> Here's an abbreviated version illustrating the behavior: https://godbolt.org/z/63G5v63h3
>
> The output is:
> ctor
> dtor
> Exception: boom
>
> The ctor/dtor are for "f1", and there is no ctor/dtor for the other "f2".
> Which means the destructor does know from where to start destroying, right?
No.
An object is only considered to have started its lifetime when the
(non-delegating) constructor for that object returns. In a
constructor, base classes are initialized first (declaration order),
then members (also declaration order), and finally the body of the
constructor. Only when an object is constructed successfully can it be
destroyed.
If a member's initialization fails via an exception, then the object
that it was a member of was *never constructed*. Its destructor does
not get called because its constructor never concluded, let alone
began. This means that the outer object never really existed.
A destructor only gets called on objects that were successfully
constructed. In the case of a member's initialization throwing an
exception, any members & base classes that were successfully
constructed up to that point are destroyed, in reverse declaration
order.
Your ultimate point, that each constructor currently already needs to
keep track of which objects have been constructed, is wrong. Because
each constructor initializes subobjects in the same order, any
particular constructor only has to keep track of how many subobjects
have been initialized before the exception. When the exception
happens, it can simply jump to the destruction code for destroying all
prior objects. Because they all share the same construction ordering,
they all share the same destruction ordering too.
What you want would require each constructor to have its own set of
destruction orderings to match their separate construction ordering.
Plus, you turn a very simple rule (subobjects are initialized in
declaration order) into a complex one (subobjects are initialized
maybe in declaration order and maybe not, depending on the
constructor). If you want C++ to be an intuitive language, one key to
that is to have simple rules.
<std-proposals_at_[hidden]> wrote:
>
> Here's an abbreviated version illustrating the behavior: https://godbolt.org/z/63G5v63h3
>
> The output is:
> ctor
> dtor
> Exception: boom
>
> The ctor/dtor are for "f1", and there is no ctor/dtor for the other "f2".
> Which means the destructor does know from where to start destroying, right?
No.
An object is only considered to have started its lifetime when the
(non-delegating) constructor for that object returns. In a
constructor, base classes are initialized first (declaration order),
then members (also declaration order), and finally the body of the
constructor. Only when an object is constructed successfully can it be
destroyed.
If a member's initialization fails via an exception, then the object
that it was a member of was *never constructed*. Its destructor does
not get called because its constructor never concluded, let alone
began. This means that the outer object never really existed.
A destructor only gets called on objects that were successfully
constructed. In the case of a member's initialization throwing an
exception, any members & base classes that were successfully
constructed up to that point are destroyed, in reverse declaration
order.
Your ultimate point, that each constructor currently already needs to
keep track of which objects have been constructed, is wrong. Because
each constructor initializes subobjects in the same order, any
particular constructor only has to keep track of how many subobjects
have been initialized before the exception. When the exception
happens, it can simply jump to the destruction code for destroying all
prior objects. Because they all share the same construction ordering,
they all share the same destruction ordering too.
What you want would require each constructor to have its own set of
destruction orderings to match their separate construction ordering.
Plus, you turn a very simple rule (subobjects are initialized in
declaration order) into a complex one (subobjects are initialized
maybe in declaration order and maybe not, depending on the
constructor). If you want C++ to be an intuitive language, one key to
that is to have simple rules.
Received on 2022-02-26 05:39:30