Search code examples
c++c++11shared-ptr

C++ "this" shared_pointer safety in class method


I have a class derived from std::enable_shared_from_this. All class objects are managed by shared pointers, thus they get destructed automatically when there are no more shared pointers pointing to them.

I have a class method which removes some shared pointers from the program's data structures, and there's a risk it removes all shared pointers to "this", i.e. the object on which the class method was called.

The question is, if really all pointers are removed, is there a chance the object is destroyed while the method runs, and the "this" pointer simply becomes invalid? If I want to ensure it doesn't happen, can I trust the system or I have to create a shared_ptr to "this" inside the method, to keep the object alive until I'm done with it? (And then if there's no more pointers, it's okay to have it destructed, once the method execution ends)

EXAMPLE:

class SharedObj : public std::enable_shared_from_this<SharedObj>
{
   /* ... */
    void do_something(SharedObj& a, SharedObj& b);
    std::shared_ptr<SharedObj> child;
};

void SharedObj::do_something(SharedObj& a, SharedObj &b)
{
   /* ... */
   a.remove_child();
   b.remove_child();
}

If a and b are the only ones who have a shared_ptr pointing to "this", then after the two remove_child() rows, there are no shared pointers pointing to "this", so besically it's supposed to be automatically destructed


Solution

  • You certainly can wind up destructing your instance from within a method by doing what you're doing. But this situation isn't specific to enable_shared_from_this, you can always call something in a method that can result in your own class's destruction. This is really only an error if you try to deference this after your class is destroyed. If you go on with regular code that doesn't modify or access the class instance, you are safe.

    What you suggested (to hold a shared_ptr to your own instance during do_something's execution) is a good idea, if you need the instance to persist for the entire function execution.