Search code examples
c++destructorobject-lifetime

Clarification about object lifetime in destructor


Another question cites the C++ standard:

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."

It would seem that this means accessing members of an object from a destructor is not allowed. However this seems to be wrong, and the truth is something more like what's explained in Kerrek SB's answer:

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.

I'm wondering if in the destructor I can pass the object's address to an outside class, like:

struct Person;
struct Organizer
{
     static void removeFromGuestList(const Person& person); // This then accesses Person members
}

struct Person
{
     ~Person() {
      // I'm about to die, I won't make it to the party
      Organizer::removeFromGuestList(*this);
}

};

This seems OK to me as I think an object's lifetime lasts until after the destructor finishes, however this part of the above answer has me doubting:

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.


Solution

  • The C++ Standard does seem to be just a little bit self-contradictory regarding the exact status of class members during execution of the destructor.

    However, the following excerpt from this Draft C++ Standard may give some reassurance that your call to the removeFromGuestList function should be safe (bold italics formatting added by me):

    15.7 Construction and destruction

    1   For an object with a non-trivial constructor, referring to any non-static member or base class of the object before the constructor begins execution results in undefined behavior. 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.

    What remains unclear (at least, to me) is whether or not referring to those class members via a reference to the object being destroyed is valid once the destructor has started execution. That is, assuming your Person class has a member, ObjectType a, is referring to person.a in your removeFromGuestList function valid?

    On the other hand, rather than passing *this as its argument, if you were to pass each required member as a 'distinct object', then you would be safe; so, redefining that function as, say, removeFromGuestList(const ObjectType& a) (with possible additional arguments) would be completely safe.