C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Relax condition for potentially invoked destructor in constructor

From: Chris Ryan <chrisr98008_at_[hidden]>
Date: Fri, 25 Feb 2022 09:41:24 -0800
Order of declaration (order of construction/reverse order of destruction)
is not the same thing as the order of the memory layout.

On Fri, Feb 25, 2022 at 9:30 AM organicoman via Std-Proposals <
std-proposals_at_[hidden]> wrote:

>
> Keep in mind that objects are guaranteed to be destroyed in the opposite
> order of construction. If you have multiple constructors that may construct
> your subobjects in different orders, you must also allocate run-time memory
> to record the order of initialization in order for your destructor to
> destroy the objects in the correct order. That's an unacceptable cost to a
> lot of people.
>
> What you are talking about here, and i guess most of the participant in
> this discussion, is the *base classes* of a *derived class* (known as
> *subobjects*).
> For that case. Yes, the order of destruction MUST follow the order of
> construction in reverse, and that is guaranteed by the standard.
>
> In our case we are talking about " *MEMBER* *Objects*", objects declared
> inside the body of the structure.
> The compiler is free to rearrange their layout however it sees fit for a
> compact memory and to avoid extra instruction to fetch a member if it is
> not at the right memory boundary.
> Imagine this situation:
> struct object
> {
> char c;
> int i;
> short s;
> };
>
> Obviously the compiler can, and maybe *must*, move the char *member*
> *object*, to the end of the list of members and add some padding to make
> the memory compact and at 4's. Making the order of initialization
> irrelevant.
>
> Again my subject is *order of initialization of data members , *
> Look at it this way:
> 1- compiler allocates memory equal to the size of all *data members plus
> base classes.*
> 2- compiler construct base classes and initialize them respecting the
> order of inheritance as pointed by the standard (left to right...etc)
> 3- at *member* *initialization*, the compiler construct *in place* the
> members. In the chunk of memory allocated for them. Using their indices
> offset and consuming their respective amount of memory.
>
> Obviously the order is irrelevant for the 3rd step.
> Since the index of the memory location where to construct the data member
> is known, and the data members doesn't rely on each other to exist!
> The memory layout is not dynamically changing because of initialization of
> the members. Right!
>
> And without even considering the above. A struct is not tightly related to
> its members declaration order.
> i.e:
> struct a { int i; double d;};
>
> is not different than
>
> struct b { double d; int i;};
>
> Memory layout and member access wise.
>
> If i want to access any member i just need to invoke its name, and the
> compiler will translate it into a pointer difference from the beginning of
> the struct location.
> ptr_mem = ptr_struct + ptr_diff
>
> So if my object is successfully constructed, and i want to destroy it, i
> don't care if i destroy "i" first or "d" first.
> Data members existance is not relying on each others in any possible way.
> Nor the object which contains them is relying on their memory layout except
> for access purpose.
>
> Again "*class subobjects <> class member objects"*
>
> A *class* *subobject* is a *member* *object* , but a *member object * is
> not a *class* *subobject*.
>
> So, i think we need to make the order of initialization of *data
> members, * irrelevant. And separate it from the *subobjects
> initialization. *
> And keep all the rest.
>
> What do you think?
>
> Nadir
>
>
> Sent from my Galaxy
>
>
> -------- Original message --------
> From: Arvid Norberg <arvid.norberg_at_[hidden]>
> Date: 2/25/22 8:14 PM (GMT+04:00)
> To: std-proposals_at_[hidden]
> Cc: organicoman <organicoman_at_[hidden]>
> Subject: Re: [std-proposals] Relax condition for potentially invoked
> destructor in constructor
>
> On Fri, Feb 25, 2022 at 9:41 AM organicoman via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> [...]
>>
>> So calling "test()" construtor, in my logic, will do the following:
>> - i want to initialize "b", but what does "f" refer to?
>> - ok let's find "f" and initialize it,
>> - good found "f", but what "a" refers to?
>> -look for "a",
>> -ok "a" is an 'int', initialized to be equal to 22.
>> - let's back track,
>> - "f", inited
>> - "b" , inited
>> - "test" constructed
>> Now in case any of the members throw an exception, then all the members
>> data that were fully constructed are allowed to call their destructor.
>> Exactly as per the standard "potentially constructed -> potentially call
>> destructor"
>>
>> That was my mental model, and that was how i would implement it.
>>
>
> Keep in mind that objects are guaranteed to be destroyed in the opposite
> order of construction. If you have multiple constructors that may construct
> your subobjects in different orders, you must also allocate run-time memory
> to record the order of initialization in order for your destructor to
> destroy the objects in the correct order. That's an unacceptable cost to a
> lot of people.
>
> When you think about it, even allowing you to define a construction order
> different from the declaration order causes a similar problem. in case the
> destructor is implicitly defined, in a translation unit where it may not
> have access to the constructor's initialization order.
>
> --
> Arvid Norberg
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2022-02-25 17:41:36