Lifetime of object is over before destructor is called?
Asked Answered
T

4

13

I don't understand this:

3.8/1 "The lifetime of an object of type T ends when: — if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or — the storage which the object occupies is reused or released."

If the lifetime ends before the destructor starts, doesn't that mean accessing members in the destructor is undefined behavior?

I saw this quote too:

12.7 "For an object with a non-trivial destructor, referring to any non-static member or base class of the object after the destructor finishes execution results in undefined behavior."

But it doesn't make clear what's allowed during the destructor.

Turk answered 23/12, 2011 at 1:48 Comment(3)
(For some reason I thought this was a duplicate, but I couldn't find one and have forgotten the answer)Turk
12.7 does not talk about what you can do in the destructor but of what happens after the end of the execution of the destructor.Antipode
You should submit this issue to the C++ committee.Cassock
B
7

The "lifetime" of an object is relevant for consumers of the object, not the object itself. Therefore a consuming class should not attempt to access members of an object once destruction has started.

Bessel answered 23/12, 2011 at 1:54 Comment(6)
What do you mean by consuming object?Turk
Any object that is using the target class. If you write a class that uses string then your class is a consumer of string.Bessel
The more common term for "consumer" is "client".Corell
This is incorrect. The lifetime is relevant for the object itself; e.g. it has to do with how virtual functions are resolved from within a destructor. "lifetime" is a specific term in the standard with specific meaning and implications, and it does not mean that "a consuming class should not attempt to access members of an object once destruction has started". It is fine to call methods while a destructor is ongoing, if the class supports it. I would recommend not assuming a class supports it unless specifically documented!Soraya
It's been a long time since I've looked the spec (or this answer) so you could very well be correct. Do you have a reference to your point about it being a "specific term".Bessel
3.8 talks about "lifetime". it refers to 12.7 which talks about what you can and can't do with an object outside of its lifetime. Do you see something there that supports this answer? (You should delete this answer, it is the top answer here but gives misleading information!)Soraya
C
9

If the lifetime ends before the destructor starts, doesn't that mean accessing members in the destructor is undefined behavior?

Hopefully not:

From N3242 Construction and destruction [class.cdtor] /3

To form a pointer to (or access the value of) a direct non-static member of an object obj, the construction of obj shall have started and its destruction shall not have completed, otherwise the computation of the pointer value (or accessing the member value) results in undefined behavior.

Cassock answered 23/12, 2011 at 1:54 Comment(3)
This answer is absolutely wrong! And yet managed to get 6 upvotes. SO is not working.Cassock
@DavidRodríguez-dribeas The answer does not answer the language-lawyer question, but very clearly proves something.Cassock
The answer is correct in that it says no this is not UB, at least. And it doesn't say anything incorrect, which makes it a stunningly good answer compared to the others here.Soraya
B
7

The "lifetime" of an object is relevant for consumers of the object, not the object itself. Therefore a consuming class should not attempt to access members of an object once destruction has started.

Bessel answered 23/12, 2011 at 1:54 Comment(6)
What do you mean by consuming object?Turk
Any object that is using the target class. If you write a class that uses string then your class is a consumer of string.Bessel
The more common term for "consumer" is "client".Corell
This is incorrect. The lifetime is relevant for the object itself; e.g. it has to do with how virtual functions are resolved from within a destructor. "lifetime" is a specific term in the standard with specific meaning and implications, and it does not mean that "a consuming class should not attempt to access members of an object once destruction has started". It is fine to call methods while a destructor is ongoing, if the class supports it. I would recommend not assuming a class supports it unless specifically documented!Soraya
It's been a long time since I've looked the spec (or this answer) so you could very well be correct. Do you have a reference to your point about it being a "specific term".Bessel
3.8 talks about "lifetime". it refers to 12.7 which talks about what you can and can't do with an object outside of its lifetime. Do you see something there that supports this answer? (You should delete this answer, it is the top answer here but gives misleading information!)Soraya
T
5

No, there's no problem:

Member objects come alive before a constructor body runs, and they stay alive until after the destructor finishes. Therefore, you can refer to member objects in the constructor and the destructor.

The object itself doesn't come alive until after its own constructor finishes, and it dies as soon as its destructor starts execution. But that's only as far as the outside world is concerned. Constructors and destructors may still refer to member objects.

Triclinium answered 23/12, 2011 at 1:56 Comment(11)
Does this mean this would be invalid?: constructor() { outside_function(this); } (could be destructor too)Turk
@Pubby: You have to be very careful with what you do with this in a constructor and destructor, since it doesn't point to a live object. Basically, "don't use it" applies. Storing the pointer is fine, but referring to the would-be object is not.Triclinium
But how can you access members without using this (assuming it is implicitly added)? constructor() { this->x = 0; this->mfun(); }Turk
@Turk there are special rules when you are in the constructor, too - because the instance is not "fully alive" yet - for example, that mfun() in this->mfun() cannot be virtual.Dews
@Pubby: inside the constructor, not all uses are invalid. For example, invoking virtual member functions may not have the intended effect, hence the "don't use it".Legendary
@Pubby: The constructor can refer to member objects (and thus "use this", if you will). What the constructor mustn't do is call an external function foo(*this) which expects a (fully constructed) object.Triclinium
@Dews "that mfun() in this->mfun() cannot be virtual." Wrong, virtual calls are virtual.Cassock
@KerrekSB Obviously, until the constructor has finished all necessary initialisations, the object cannot be used where a fully constructed object is needed. The problem you are trying to point out isn't very clear.Cassock
@Cassock #962632Dews
@Dews Yes, and virtual functions are virtual in constructor.Cassock
Some of these answers are wrong, or at least misleading. It's ok to call virtual functions from a constructor – but the behavior might not be what you expect so beware. (§ 12.7/4) It's also ok to pass this out to another function, and for other functions or even threads to use the object – assuming the class supports it. Be careful. And keep in mind that most objects you use might not support this; in particular standard library objects don't support concurrent use of an object being constructed or destroyed unless otherwise specified §17.6.4.10/2.Soraya
S
2

"Lifetime" doesn't mean that. It is a precisely defined term in the standard that has a variety of implications, but it might not have all the implications that you would think. Members can still be used during construction and destruction, outside code can call member functions, etc, etc.

Granted, it's a bit odd for client code to call member functions concurrently with the destructor, but not unheard of and certainly not disallowed by the language. In particular, std::condition_variable explicitly allows the destructor to be invoked while there are outstanding calls to condition_variable::wait(). It only prohibits new calls to wait() after the destructor starts.

Soraya answered 12/1, 2017 at 18:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.