Search code examples
c++memory-managementassignment-operatordelete-operatordouble-free

difference between `delete this` and `this->~Obj` in C++


When I am writing a demo string class, in the copy assignment function, I try to clear itself through 'delete this' before copy.But it failed.

    Str &operator=(const Str &s) {
        if (this != &s) {  // self-assignment check
            //delete this; //cannot run as I imagine
            this->~Str();  
            _size = s._size;
            _str = new char[_size + 1];
            memcpy(_str, s._str, _size + 1);
        }
        return *this;
    }
    ~Str() {
        _size = 0;
        delete[] _str;
    }

the linux told me

double free or corruption (out) Aborted (core dumped)


Solution

  • delete x; is equivalent to x->~T(); followed by operator delete(x) (which is similar to free(x), but might be incompatible with it).

    x->~T(); is a dangerous tool. In this case it must be followed by new(this) T(...); (placement-new) to call a constructor, otherwise the current object is considered to be "dead", and any interaction with it causes undefined behavior.

    But even if you do call placement-new, it can throw. Then the object remains dead, and the caller gets UB when it tries to destroy the already dead object again.

    Conclusion: x->~T(); is hard to use correctly, use something else.

    • Either write a function that does the same thing as the destrutor, and call it instead. Unlike the destructor, the object wouldn't be considered dead after calling it, so no placement-new is needed.

    • Or use the copy&swap idiom. Write the assignment as:

      Str &operator=(Str s) noexcept
      {
          std::swap(_str, s._str);
          std::swap(_size, s._size);
          return *this;
      }
      

      This is an universal way of writing assignments. It works both as copy and move assignment, is exception-safe, etc.