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

127 Views Asked by At

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)

2

There are 2 best solutions below

3
HolyBlackCat On BEST ANSWER

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.

1
user10 On

Your delete this already executes this->~Str() but that's only one problem. After delete this you call _size = s._size which is actually this->_size = s._size. But lifetime of this already ended so any call to this can lead to undefined behavior. So not delete this nor this->~Str() belong to your assign operator.