Boost logo

Boost Users :

Subject: Re: [Boost-users] enable_shared_from_this()
From: Travis Gockel (travis_at_[hidden])
Date: 2013-02-05 20:32:44


On Tue, Feb 5, 2013 at 2:10 AM, Dominique Devienne <ddevienne_at_[hidden]>wrote:

> On Mon, Feb 4, 2013 at 6:23 PM, Nathan Crookston
> <nathan.crookston_at_[hidden]> wrote:
> >> Since Foo embeds a weak_ptr, why can't it new the pi_ on the spot?
> >> (I'm using Boost 1.44).
> >
> > Hmm, it might be interesting to have shared_from_this create a
> shared_ptr if
> > none exists, but I don't know what that might complicate -- perhaps it
> would
> > cause issues at destruction?
>
> I don't see the difference between the shared_ptr being created from
> the "inside" or the "outside", as far as that pi_ is concerned.
>
> >> PS: On a related note, why doesn't boost::shared_ptr<Foo>(p_foo)
> >> (where p_foo is a raw Foo*) implicitly apply the aliasing Ctor, to
> >> share the same px, to avoid the classic bug of having several
> >> different pn on the same px, since p_foo derives from
> >> enable_shared_from_this()? Initially i thought that's what
> >> sp_enable_shared_from_this() and pe->_internal_accept_owner() were
> >> meant to do, but obviously that's not the case.
> >
> > I suspect something like this could be made to work if the previous also
> > worked -- but the class is documented to *not* allow the previous to
> work.
> > I'd have to think about why (or maybe Peter will enlighten us).
>
> Indeed, I (naively) think it can work, and I'm interested in finding
> out why this was not implemented, especially whether it was conscious
> decision (rational?) or simply overlooked.
>

Consider this simple example:

int MyThing::Foo()
{
    shared_from_this();
    return this->x;
}

If enable_shared_from_this created a shared_ptr for you, then the last
reference would have been destroyed and this would be deleted, leading to
undefined behavior. A real-world example might be passing
shared_from_this() as part of a callback to some function (or any other of
the uses of enable_shared_from_this). Your proposal would make
legitimate-looking code lead to undefined behavior depending on how the
instance was constructed (if it was stored in a shared_ptr). This would be
doubly-confusing if you used shared_from_this() in the constructor. And
then you'd have to figure out a way to let a unique_ptr<MyThing> know that
it no longer uniquely owns the instance. Or somehow deal with a
stack-allocated MyThing.

In the current implementation, the call to shared_from_this() will
*always* throw
a boost::bad_weak_ptr. Sure, it is inconvenient, but it doesn't lead to
undefined behavior. I see that as a major advantage.

> Thanks for any insight on this. Could very well be I'm missing
> something obvious (my C++ expertise doesn't rise to Boost levels), but
> so far I fail to see the drawbacks.
>

I would suggest looking at intrusive_ptr (
http://www.boost.org/doc/libs/1_52_0/libs/smart_ptr/intrusive_ptr.html) or
the not-really-documented enable_shared_from_this2 (
http://www.boost.org/doc/libs/1_52_0/boost/smart_ptr/enable_shared_from_this2.hpp).
Neither solves
every problem under the sun, but they might have helpful properties you're
looking for.

There's already code that tightly couples
> shared_ptr/weak_ptr/enable_shared_from_this,

I would disagree with the statement that shared_ptr and weak_ptr are
coupled with enable_shared_from_this -- they can exist perfectly fine
without them (but enable_shared_from_this can't exist without both). The
only coupling shared_ptr has with weak_ptr is inside the implementation
(arguably bad, but whatever).

-- 
Travis Gockel
ë Combinator


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net