
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