Subject: Re: [boost] [smart_ptr] enable_shared_from_this and shared_ptr to a base class
From: Jonathan Wakely (jwakely.boost_at_[hidden])
Date: 2013-06-24 06:05:44


On 24 June 2013 10:22, Adam Romanek wrote:
> On 06/24/2013 10:06 AM, Jonathan Wakely wrote:
>>
>>
>> The documentation says that there must be a shared_ptr that owns t,
>> where t is an instance of T (in your case T is Y). That is not true
>> for your program, for a shared_ptr to "own" a pointer t it must have
>> been constructed with a copy of _that_ pointer, not some other pointer
>> with a different type to some base class of the same object. The
>> shared_ptr owns the pointer it was constructed with, and you do not
>> construct it with a Y*, so no shared_ptr owns a pointer to your Y
>> object.
>
>
> When taking inheritance into account one can safely say that a pointer to a
> base class X pointing to an instance of a derived class Y owns this
> instance. That's my point of view.

No, that's not how shared_ptr's ownership works. It owns a pointer
and when the last owner releases ownership the pointer is passed to
the deleter (which might just call 'delete'). But there is no
requirement that the pointer is non-null, or points to an instance of
some specific type, and certainly no requirement that if the
shared_ptr owns an X* that it has anything to do with any instance of
a different type Y, even if Y is related to X by inheritance. The
shared_ptr doesn't care about such things, it just owns a pointer and
arranges for it to be passed to the relevant deleter at the
appropriate time.

In this example the four shared_ptr objects all share ownership of the
same pointer of type Y*, even though one of them is a shared_ptr<X>
and one is shared_ptr<void> and one stores a completely unrelated
pointer type, but still owns a pointer of type Y*:

struct X { virtual ~X() {} };
struct Y : X { };

std::shared_ptr<Y> sy(new Y);
std::shared_ptr<X> sx(sy);
std::shared_ptr<void> sv(sx);
std::shared_ptr<int> si(sv, (int*)0);

The ownership is a property of the static type of the pointer passed
to the first shared_ptr constructor that creates a unique shared_ptr
(i.e. one with use_count()==1). If you don't pass a Y* to the first
constructor then it doesn't own a Y* and won't initialize any
enable_shared_from_this<Y> base class.

> So maybe "ownership" should be described in more detail?

Yes, if people are making up their own interpretations of it then
maybe it should be.