Boost logo

Boost :

Subject: Re: [boost] Weak pointer to object not managed by a shared_ptr
From: Mateusz Loskot (mateusz_at_[hidden])
Date: 2009-09-02 15:18:36

Ryan Gallagher wrote:
> Mateusz Loskot <mateusz <at>> writes:
>> 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.

I see. IOW, the idea is to make a weak association between objects
and avoid crashes caused by dereferencing invalid pointer.

>> 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.


>> 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.

The confirmation of UB is enough for me, however...

> 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.

simple testes using GCC 4.3 and Visual C++ 9.0 show that destruction
occurs in different point than we expect:

1) I added verbose destructor to X

~X() { cout << "X dtor\n"; }

2) Compiled and executed the following use case of X:

shared_ptr<X> spx;
    X x1(7);
    spx = shared_ptr<X>(x1.get_weak_ptr());
} // *** x1 is being destructed
cout << spx->get_i() << std::endl;

mloskot_at_dog:~$ g++ -Wall -pedantic weak_ptr_local.cpp
mloskot_at_dog:~$ ./a.out
X dtor

So, x1 is destructed but its value of 7 is still accessible.
I assume I'm observing UB here. I understand nature of UB and that
it can give unexpectedly 'correct' results.

Shortly, this is UB and one should always assume the point of x1
object destruction (marked with ***) is when the execution
leaves the scope in which x1 was declared.

Is this correct?

> 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.

So, the weak_ptr acts as a flag indicating if pointee is still
alive (a self-indicator). Alternative would be to cache some boolean
indicator and check it instead of the weak_ptr, before accessing
object of X.

>> 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.

Yes, this is clear.

> 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.

Yes, however get_i() returns the value stored in x1. It's UB anyway.

> 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.

Yes, I understand this kind of use cases. It makes sense to me.

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

I wouldn't code this way too.

Thanks all for helping me to understand it better!

Best regards,

Mateusz Loskot,
Charter Member of OSGeo,

Boost list run by bdawes at, gregod at, cpdaniel at, john at