Boost logo

Boost :

Subject: Re: [boost] Weak pointer to object not managed by a shared_ptr
From: Ryan Gallagher (ryan.gallagher_at_[hidden])
Date: 2009-09-02 12:55:03


Mateusz Loskot <mateusz <at> loskot.net> writes:
> One of the smart pointer techniques [1] explains use of weak_ptr
> pointer to object not managed by a shared_ptr.
>
> [1] http://www.boost.org/doc/libs/1_40_0/libs/smart_ptr/sp_techniques.html

Interesting, I had never read, nor thought of that before.

> I'm wondering what would be practical use case of that?

I think the use case is for when you have an object that needs to
reference an X instance (from your example) but doesn't have any
knowledge of the lifetime of that X instance. Thus, instead of
using a C++ reference or pointer that object can hold a
weak_ptr<X> -- enabling it to check if the X instance is still
alive when it needs to use it.

> Is it a part of any of known idioms or patterns?

I don't think so. I think this use-case (referencing but not knowing
the lifetime) is something that should probably be avoided in one's
design. However, if it's impractical to do so then this would
just make it safer than using a raw pointer or C++ reference.

The safety is questionable though in a multi-threaded environment
unless you also block the destruction when creating the
shared_ptr from the weak_ptr. It's best if you design accounts
for object lifetimes in associated classes.

> Also, is it valid to assume that this technique can extend lifetime of X
> so of the internal integral X::i_ ?

No. The example you have is undefined behavior as the X instance
is destructed when it goes out of scope. Your just using the
shared_ptr<X> to reference the destroyed X instance. This is the
same as if you had held a raw pointer to that X instance after it
was destructed.

The whole point is to just hold a weak_ptr<X> until you actually
need to use it. At that point you can check whether the X instance
is still alive.

<snip>
> shared_ptr<X> spx;
> {
> X x1(7);
>
> // XXX: lifetime is extended here?
> spx = shared_ptr<X>(x1.get_weak_ptr());
> }
>
> // XXX: No exception. x1 is still alive, so the pointer valid?
> cout << spx->get_i() << std::endl;

x1 is not alive, it was destructed at scope exit. The
shared_ptr<X> that it held was also destructed at this point.
You just kept the ref-count up through spx even though it refers
to a destroyed object. Check the ref-count at this point, it
should be 1.

<snip>
> However, if I replace retrival of shared_ptr with weak_ptr then of
> course bad_weak_ptr exception is thrown:
>
> shared_ptr<X> spx;
> weak_ptr<X> wpx;
> {
> X x1(7);
> wpx = x1.get_weak_ptr();
> }
> spx = shared_ptr<X>(wpx);
> cout << spx->get_i() << std::endl;

This is more proper usage (though not very helpful here).

<snip>
> I would appreciate if anyone could help me to understand it.
<snip>

For using this, think about X lifetimes being managed by some other
class (XManager). Think about another class A that isn't managed
my XManager but needs to weakly reference some X instance.

Perhaps someone else can give a better, more realistic, example
though, as even this one I wouldn't code this way.

HTH,

-Ryan


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk