C++ – How to Determine if it’s Safe to Move Object Inside Its Destructor

c++

I'm 99% sure the answer to my question is 'Yes'. I just want to double check my assumption is right and I want to be sure that there is nothing in the upcoming C++ standards that could change the rules (like destructive move if it is really possible).

So, my case is as following. I have an object of the Request type whose lifetime is managed by std::shared_ptr<Request>. When the object is about to die (i.e. the ref counter is zero and std::shared_ptr is calling the ~Request destructor) I need to check some condition and create another instance of the Request type with exactly the same data. Basically I just need to prolong the subscription.

The cheapest way from my point of view is just to call the move ctor of the Request class:

Request::~Request()
{
  if(condition)
  {
    service.subscribe(std::make_shared<Request>(std::move(*this)));
  }
}

As far as I know all data members of the Request instance in the context of destructor are still alive. They are not destroyed yet. So it has to be safe to move them somewhere, right? Is my assumption in line with the idea of C++ and I'm not doing anything stupid?

Related questions:

Best Answer

In the end, the line service.subscribe(std::make_shared<Request>(std::move(*this))); might be legal because:

The lifetime of an object o of type T ends when:
(1.3) if T is a non-class type, the object is destroyed, or
(1.4) if T is a class type, the destructor call starts, or
(1.5) the storage which the object occupies is released, or is reused by an object that is not nested within o

I emphazised the relevant line.
https://timsong-cpp.github.io/cppwp/n4861/basic.life#1.4

Yet, a few lines later:

6 Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that represents the address of the storage location where the object will be or was located may be used but only in limited ways. For an object under construction or destruction, see [class.cdtor].

https://timsong-cpp.github.io/cppwp/n4861/basic.life#6

(Again emphasize is mine)

Following [class.cdtor] link:

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.

https://timsong-cpp.github.io/cppwp/n4861/class.cdtor#1

A contrario, we may understand that other usage are legal (otherwise, as stated by @interjay in comment, destructors would be effectively useless).

From the snippet, its not possible to tell if there are no other issues (see the question comments).