Question

Related to Same address, multiple shared_ptr counters, is it forbidden by C++ standard? and myriad other questions around multiple shared_ptr objects pointing to the same object but not sharing the underlying ref count structure.

What happens if the object inherits from "enable_shared_from_this" in the above mentioned question? What does my shared_from_this() return? One with the custom deleter or the one without?

struct B : boost::enable_shared_from_this<B> {
  boost::weak_ptr < B > get_weak() {
    return shared_from_this();
  }
};

void doNothing(B *) {
}

int main() {
  B * b0 = new B;

  boost::shared_ptr < B > sddb0(b0, doNothing);
  boost::weak_ptr < B > swddb0(sddb0->get_weak());
  //  Does this have a custom deleter???
  boost::shared_ptr < B > sddb1 = swddb0.lock();

  boost::shared_ptr < B > scdb0(b0);
  boost::weak_ptr < B > swcdb0(sddb0->get_weak());
  //  Does this *not* have a custom deleter???
  boost::shared_ptr < B > scdb1 = swcdb0.lock();
}
Was it helpful?

Solution

The deleter is associated with the owned object and will be used to dispose of it when the last owner drops its reference, so all pointers that share ownership of the same object also share the deleter. The deleter is not stored in individual shared_ptr objects, it's stored on the heap along with the reference counts, so shared by all the objects that share the same counts.

So let's looks at your code. First, I had to fix your code as it didn't even compile as shown. It's always a good idea to test the code in your question, to avoid wasting people's time by making them fix typos and add missing headers.

Don't write this:

B * b0 = new B;

boost::shared_ptr < B > sddb0(b0, doNothing);

The correct way to do that is:

boost::shared_ptr < B > sddb0(new B, doNothing);

The enable_shared_from_this<B> base has a weak_ptr<B> member which gets assigned to by the shared_ptr constructor, so that weak_ptr shares ownership with sddb0, as does the shared pointer returned by shared_from_this().

So the answer to this question is yes:

//  Does this have a custom deleter???
boost::shared_ptr < B > sddb1 = swddb0.lock();

sddb1 shares ownership with sddb0 so has the same deleter.

You could test that by using get_deleter, or by writing to stdout in doNothing, or by using owner_less to compare the owners of the pointers.

This creates an object that does not share ownership with the existing shared pointers:

boost::shared_ptr < B > scdb0(b0);

The enable_shared_from_this<B> base's weak_ptr<B> member gets re-assigned to by the line above, so it shares ownership with scdb0 instead of sddb0. So when you call get_weak after that point it returns a weak pointer that shares ownership with scdb0 and so doesn't have a custom deleter. Again, you can easily verify that by seeing that doNothing isn't called, or by using owner_less.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top