The "this" reality in the destructor

In the last line of the destructor, I have a diagnostic type message that takes the form printf -like:

 "object destroyed at %p", this 

I have a problem though about how well this defined at such a point.

Should I make such reservations? Is the behavior correct?

+6
source share
5 answers

According to the C ++ standard (12.4 Destructors)

8 After executing the body of the destructor and destroying any automatic objects allocated inside the body , the destructor for class X calls destructors for Xs of direct non-invariant non-static member data, destructors for direct base classes of Xs and, if X is the type of the derived class itself (12.6.2), its destructor calls destructors for the virtual base classes of Xs.

So your code is well formed. All destructors of non-static data elements and base classes are called after the execution of the body of the destructor.

+7
source

Well, the pointer itself definitely exists (it's just an address, after all). No need to print the value of a pointer.

On the other hand, everything you did in the destructor has already happened. Attributes may have already been delete , etc., so you need to avoid anything that accesses them.

+2
source

This has a very well-defined behavior. Consider that the this pointer can be used implicitly or explicitly in the entire destructor, for example. whenever you access a member variable for things like delete ptr_; . After the destructor returns, members are destroyed in the reverse order of declaration / creation, and then the base destructors are called.

+1
source

As you could now, you can access your class members from the destructor. This does not work if the this pointer is invalid. Thus, you can safely assume that the this address points to the same thing that you could type in the constructor.

0
source

Inside the destructor, the this pointer is well defined, as are all members and bases (which will be destroyed in the reverse order of the construct after the destructor returns). Therefore, printing the address to which it refers is not UB.

The only thing is that the object itself cannot be considered "polymorphic", since the derived components have already been destroyed.

 class A { public: virtual void fn() { std::cout << "A::fn" << std::endl; } virtual ~A() { fn(); } //< will call A::fn(), even if B is destroying }; class B: public A { public: virtual void fn() { std::cout << "B::fn" << std::endl; } virtual ~B() {} }; int main() { B b; A& a = b; a.fn(); //< will print B::fn(), being A::fn virtual and being B the runtime-type of the a referred object return 0; //< will print A::fn() from b A component destructor } 
0
source

Source: https://habr.com/ru/post/974736/


All Articles