Calling destructor in member function

If we are implementing, for example, smart pointers, and we want to do a = std::move(b) --- we need to delete memory to which a is pointing, but can we call destructor inside move assignment operator, instead of copy-pasting destructor's function body?

Is the behavior on calling destructor inside move-assignment defined?

If it's not, are there any better ways dealing with it rather than copy-pasting destructor's body?


You are allowed to call the destructor on this inside a member function and it has well-defined behavior.

However, that behavior involves ending the lifetime of the object *this. After the destructor call you are not allowed to access/use any members of the object anymore. This also has bad consequences in many situations, e.g. if the object has automatic storage duration the destructor will be called a second time on it during scope exit, which would cause undefined behavior.

So that isn't useful for what you want to do.

Although I strongly advice against it, in theory you could then follow the destructor call by construction of a new object at the same storage location via placement-new. However there are some preconditions outside the control of the class on when this is allowed without causing undefined behavior down the line. Under some conditions such a placement-new itself might be undefined behavior, under some conditions the names/references/pointers referring to the old object will not refer to the new one causing undefined behavior if used after the placement-new and under some conditions the lifetime of any parent object that *this is a subobject/member of will also be ended by such an operation, causing undefined behavior if used afterwards.

You can see a demonstration on how this would be implemented, against my advice and under certain (unstated) assumptions, in the standard (draft): https://timsong-cpp.github.io/cppwp/n4868/basic.life#example-2

The linked example and the paragraph preceding it don't spell out all the conditions and possible problems with the approach that I hinted at above. Only the very specific usage of the class/function shown in the example is definitively allowed.


If you just want to reuse code, move the body of the destructor into a new member function and call that one from both locations requiring the same behavior.


Explictly calling destuctor is technically available, you can use this->~Object() in non static method of the class Object.

However this is a bad practice. Consider use these instead.

class Test {
 public:
  Test() {}

  ~Test() {
    Deallocate();
  }

  Test(const Test& other) = delete;

  Test(Test&& other) {
    Deallocate();
    // Do sth
  }

 private:
  void Deallocate() {
    // Do sth
  }
};