6

I am new to C++11 and I came across enable_shared_from_this. I do not understand what it is trying to achieve? So I have a program that uses enable_shared_from_this.

struct TestCase: enable_shared_from_this<TestCase>
{
std::shared_ptr<testcase> getptr() {
    return shared_from_this();
}

~TestCase() { std::cout << "TestCase::~TestCase()"; }
};


int main()
{
std::shared_ptr<testcase> obj1(new TestCase);
std::shared_ptr<testcase> obj2 = obj1->getptr();
// The above can be re written as below
//  std::shared_ptr<testcase> obj2 = shared_ptr<testcase>(obj1);
}

My question is when I need a pointer to 'this', why not use the obj itself. Why to return a 'this' from a function of that class like using getptr() and then returning shared_from_this()???? I do not understand.

Second question, if enable_shared_from_this is NOT used, why is the dtor called twice that creates a problem, a crash!!!!

Another way I can bypass using enable_shared_from_this is like this. Add this in class TestCase

  std::shared_ptr getptr1(shared_ptr obj) {
   return std::shared_ptr(obj);
  }

and from main make a call this this:

  std::shared_ptr bp2 = bp1->getptr1(bp1);

And done. We do not need enable_shared_from_this. Why on the earth do we need it??

Eliad
  • 894
  • 6
  • 20
Bhathura
  • 61
  • 5
  • It's described quite reasonably [here](http://en.cppreference.com/w/cpp/memory/enable_shared_from_this). – baderman Mar 16 '16 at 16:31
  • "why not use the obj itself" this will make a copy, which is not what you want when you use `shared_from_this` – Chris Beck Mar 16 '16 at 17:01

2 Answers2

9

A shared_ptr manages two different things. It has a pointer to its data, and a pointer to a reference counting block.

The reference counting block has a strong counter, a weak counter and a destroy operation in it.

When you std::shared_ptr<X>(pX), it creates a new reference counting block that, when the last (strong) reference goes away, it deletes the pX object.

The same thing happens when you std::shared_ptr<X>(this).

So, if you wrap an object in std::shared_ptr in two different spots, you have to different reference counting blocks, and they both want to destroy the object when they go away.

enable_shared_from_this<X> changes how this works. When you create a shared pointer to an object inheriting from it, it stores a std::weak_ptr<X> inside the enable_shared_from_this<X>. A weak pointer stores a pointer to the above reference counting block, but only "holds" a weak reference (not a strong one).

Then, when you call shared_from_this(), it does a .lock() on that weak pointer and returns a shared pointer using the reference counting block of the old one created (as stored by the weak_ptr).

Now, the above is an example implementation of what it could do: the standard mandates behavior, not implementation, and the weak_ptr is a possible way to implement it. Similarly, the reference counting block detail is just an example implementation.

The core issue is that two independent shared pointers wrapping the same pointer will try to independently manage the pointer's lifetime. enable_shared_from_this makes the first smart pointer's reference counting block be used by later shared_from_this() return values.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
7

Short answer: you need enable_shared_from_this when you need to use inside the object itself existing shared pointer guarding this object.

Out of the object you can simply assign and copy a shared_ptr because you deal with the shared_ptr variable as is. But when you are in one of the class members then if you need to use a shared pointer pointing to self object (instead of ordinary this) and there is no such shared pointer in arguments of that method then shared_from_this() is what will help you. Using std::make_shared(this) is absolutely unsafe as you can not have two shared pointers on the same object. While, shared_from_this() is safe because it uses weak_ptr to "resolve" already existing shared_ptr.

To be able to use shared_from_this() you must first use enable_shared_from_this in your class definition which adds a shared_from_this() method to your class.

Note, shared_from_this() can not be used in the class constructor! At that time the shared_ptr does not exist yet, so the shared_from_this() can't resolve any exisiting pointers.

And when and why one can need a shared pointer to this instead of just this it is quite other question. For example, it is widely used in asynchronous programming for callbacks binding.

Evgeny S.
  • 838
  • 4
  • 12
  • 1
    This is the first useful answer I see about why one might want to use enabled_share_from_this. A concrete example would be great too if you know one. Until I see a nice example, using enabled_shared_from_this will look like a bad design choice to me. – Arnaud Apr 19 '16 at 13:43