Reputation: 118
I'm trying to understand what is allowed to do in destructors.
The standard says: "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".
cppreference describes destruction sequence this way: "For both user-defined or implicitly-defined destructors, after the body of the destructor is executed, the compiler calls the destructors for all non-static non-variant members of the class".
Does this mean, that in the following code calling method from its member's destructor is UB? Or by "referring" standard means something particular?
struct Foo {
Foo(Callback cb) : cb_(cb) {}
~Foo() {
// body of Bar destructor finished at this moment;
// cb_() calls Bar::call_me()
cb_();
}
Callback cb_;
};
struct Bar {
// pass callback with captured this
Bar() : foo_([this]() { call_me(); }) {
}
void call_me() {
}
// foo is a member, its destructor will be called after Bar destructor
Foo foo_;
};
Also, what does the phrase "after the destructor finishes" from the standard mean exactly? After the body of a destructor finishes? Or after all members and base classes destroyed?
I think the answer to the last question is the key to understanding what is allowed and what is not.
Upvotes: 4
Views: 186
Reputation: 238351
The destructor of Bar
has not finished, and therefore referring to a member of Bar
, and indeed calling a member function of Bar
within its destructor is OK.
Calling member functions of the super object can be a bit precarious though, since member functions may access sub objects, and some sub objects may have already been destroyed by the time the member function is called, and in that case accessing the destroyed objects would result in undefined behaviour. This is not the case in your example.
Or by "referring" standard means something particular?
I think it means to form a pointer or a reference to a sub object. As is done in the example below the rule.
Also, what does the phrase "after the destructor finishes" from the standard mean exactly? After the body of a destructor finishes? Or after all members and base classes destroyed?
The latter.
The body is executed first, then the destructor calls the sub object destructors, and then the destructor has finished.
Upvotes: 3