Is it safe to `delete this`? [duplicate]
Asked Answered
A

10

35

In my initial basic tests it is perfectly safe to do so. However, it has struck me that attempting to manipulate this later in a function that deletes this could be a runtime error. Is this true, and is it normally safe to delete this? or are there only certain cases wherein it is safe?

Albumenize answered 15/2, 2009 at 2:25 Comment(1)
I disagree. The two questions linked to ask about a specific case and when one would use delete this. I ask if it's safe in the general sense, and when it isn't.Angara
W
47

delete this is legal and does what you would expect: it calls your class's destructor and free the underlying memory. After delete this returns, your this pointer value does not change, so it is now a dangling pointer that should not be dereferenced. That includes implicit dereferencing using the class's member variables.

It is usually found in reference-counted classes that, when the ref-count is decremented to 0, the DecrementRefCount()/Release()/whatever member function calls delete this.

delete this is typically considered very bad form for many reasons. It is easy to accidentally access member variables after delete this. Caller code might not realize your object has self-destructed.

Also, delete this is a "code smell" that your code might not have a symmetric strategy for object ownership (who allocates and who deletes). An object could not have allocated itself with new, so calling delete this means that class A is allocating an object, but class B is later freeing it[self].

Williemaewillies answered 15/2, 2009 at 2:36 Comment(4)
Technically, your last paragraph is incorrect. While it is true that an object could not have allocated itself, this doesn't imply where you go next. It does not therefore follow that a different class allocated it. A static factory method on the same class could have done the creation.Encrimson
"delete this is typically considered very bad form for many reasons." i think that is why well designed ref-counted classes do not use delete this; . they use the handle/body idiom. in my opinion, using delete this is almost always a bad idea. (well, i don't know any reason - but im being careful)Trinia
You don't mention you cannot call delete this in a destructor.Saunders
What if one copies a member variable into an automatic storage variable, then deletes this, then accesses the stack variable: is the compiler going to produce expected code, or is it allowed to optimize out the copy and still access the member variable, which is now UB?Ng
L
17

It's safe to delete "this" as long as it's essentially the last operation in the method. In fact several professional level APIs do so (see ATL's CComObject implementation for an example).

The only danger is attempting to access any other member data after calling "delete this". This is certainly unsafe.

Livengood answered 15/2, 2009 at 2:28 Comment(2)
There is also the danger of calling delete this in a destructorSaunders
@Saunders Infinite recursion!Bid
P
15

Delete this is perfectly legal as others have already mentioned. It is risky for one additional reason that hasn't been mentioned yet - you are assuming that the object has been allocated on the heap. This can be difficult to guarantee, although in the case of reference counting implementations isn't generally a problem.

Prajna answered 15/2, 2009 at 2:41 Comment(3)
Great point. "delete this" should really only be done if you know for certain how the object was created. This usually means having a private constructor of some sort.Encrimson
In my case, it's inside a state machine, so when the current state is done, it makes a new state and replaces the only pointer to it in the state handler and then delete thiss itself.Angara
The "proper" solution is to have a private destructor. The object can then call delete this, but you can not establish a stack based version.Padraig
R
15

but dont do it in the destructor !

Rosaleerosaleen answered 15/2, 2009 at 2:41 Comment(1)
in constructor you can do it unless class has non-trivial destructorDesist
S
6

As stated by others, delete this is a valid idiom but for it to be safe you have to ensure that the object is never instantiated on the stack.

One way to do this is to make both the constructor and the destructor private and enforce object creation through a class factory function which creates the the object on the heap and returns a pointer to it. The class factory can be a static member function or a friend function. Cleanup can then be done through a Delete() method on the object that does the "delete this". COM objects basically work this way except that in addition they are reference counted with the "delete this" occurring when the reference count is decremented to zero.

Suannesuarez answered 15/2, 2009 at 2:41 Comment(0)
E
3

Yes. It should be perfectly fine. "This" is just a pointer. Any pointer will do for delete. The information on how to delete an object is contained in the heap records. This is how IUnknown::Release() is usually implemented in COM objects.

Encrimson answered 15/2, 2009 at 2:28 Comment(0)
P
3

delete this can cause an issue when you have subclasses of the object you are deleting. Remember construction starts from top down and deletion starts from bottom up. So if delete this is in the middle of the hierarchy you basically lost all the objects below this particular class.

delete this comes very handy when you are implementing a reference counted object, an example of which is the COM classes.

Painter answered 15/2, 2009 at 2:38 Comment(2)
What do you mean when you say "you have basically lost all the objects below this particular class? Can you explain this? Perhaps provide an example?Prajna
Your example is only true if you don't use virtual destructor. So in a sense you are totally right, but then again a hirarchy withou virtual destructors is pure evil, so one 'should' never see it happen.Balsamiferous
P
2

Read for a similiar discussion. Your understanding is right in that it does work, is needed, and can be dangerous since you can't access this afterwards.

Padraig answered 15/2, 2009 at 2:30 Comment(0)
B
2

Legal Yes
Safe No

Blarney answered 15/2, 2009 at 6:46 Comment(0)
P
-2

If you are inheriting from a base class and gave delete this in the base class function, using derived class pointer will cause a crash. E.g:

class Base
{

    virtual void Release()
    {
        delete this;
    }

}

class Derived : public Base
{

    void Foo()
    {
        ...
    }

}

main()
{

    Base *ptrDerived = new Derived();
    ptrDerived->release();
    ptrDerived->Foo() //Crash

}
Peppers answered 4/2, 2016 at 9:24 Comment(1)
What did you expect? Any use of a deleted object is UB, hence crash or worse. This isn't specific to delete this at all. Did you somehow expect that the Derived part of the object would remain alive? Then you don't know anything about C++ object lifetime. Also, which is it: Release() or release()?Biology

© 2022 - 2024 — McMap. All rights reserved.