Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost.enable_shared_from_this and create another shared_ptr<T>

Recently, I came across a problem with boost smart pointer. To be specified, enable_shared_from_this keeps a "this" shared_ptr to the class T. When an instance of T is out of the scope, enable_shared_from_this still remains. But what about I create a new object of shared_ptr of the original ptr? And what is the difference?

Many thanks.

class Foo : public boost::enable_shared_from_this<Foo>
{};

int main() {
  shared_ptr<Foo> p1(new Foo);
  shared_ptr<Foo> p2 = p1->shared_from_this();
  shared_ptr<Foo> p3 = shared_ptr<Foo>(p1);

  p1.reset();
  // p1 is released, p2 and p3 still remains.
  // but what is the diff between p2 and p3?
  // Can I say shared_from_this() works the same way as
  // shared_ptr<Foo>(p1);
}
like image 640
Tony Chen Avatar asked Dec 11 '25 00:12

Tony Chen


1 Answers

It will likely crash your program when your new pointer goes out of scope. The reason for that is that shared_ptr controls the lifetime of your object by counting references to it. Everytime you copy shared_ptr it increases ref count, every time shared_ptr object goes out of scope, it decreases ref count. When ref count reaches zero, it will delete object. When shared_ptr you created inside of the class method will go out of scope, it will delete this, because the ref count will be zero.

So shared_from_this should be used, when you need a shared_ptr inside of the class member function, whereas in any other case, you can just use a shared pointer to object.

Consider this example:

class Y
{
public:

    shared_ptr<Y> f()
    {
        return shared_ptr<Y>(this);
    }
}

If you returned ordinary shared pointer here, you'd create multiple shared_ptrs to the same pointer, which would then, at some point delete this, while leaving all other shared_ptr instances as dangling (pointing to something that was deleted). So, correct version is:

class Y: public enable_shared_from_this<Y>
{
public:

    shared_ptr<Y> f()
    {
        return shared_from_this();
    }
}
like image 99
lisu Avatar answered Dec 12 '25 12:12

lisu