I ask this because it's a debilitating restriction for a number of obvious reasons yet I am sure the C++ standard guys had a good reason for doing it, and I'd like to know what it is. Not because it will make any difference but because it will make me feel better knowing that there's a good reason for it.
Here is my current take on it; as I see it weak pointers have 2 main uses:
1) to avoid ownership loops. 2) to reduce overhead associated with bouncing around lots of shared pointers.
The former would be no less served and the latter better served by implementing weak_ptr.get(), so why doesn't it exist? More to the point, wouldn't weak_ptr.get() be more efficient than weak_ptr.lock().get(), or can a compiler optimize this to be the same?
A weak pointer needs to be able to check whether the smart pointer it references is still valid. If it couldn't do that, then you couldn't know whether the result from get
was valid by the time you actually used it.
That's why there's lock
; it gives you a smart pointer that will be valid for as long as you need it (which isn't expected to be very long).
If you want direct access, then what you really want is an ordinary "dumb" pointer.
1) to avoid ownership loops. 2) to reduce overhead associated with bouncing around lots of shared pointers
The former would be no less served and the latter better served by implementing weak_ptr.get(), so why doesn't it exist? More to the point, wouldn't weak_ptr.get() be more efficient than weak_ptr.lock().get(), or can a compiler optimize this to be the same?
Former true, latter is wrong - weak pointers aren't magically low-cost shared pointers... they're functionally different. You need to pick one that suits your situation.
The main reason to use weak pointers is to keep track of some data that you might want to use if it's still hanging around, but can happily survive without. Establishing that involves a race condition with users of the shared pointers, so unless you have some insider insight into the lifetime of the object that means you can be certain your code can complete before the object's destroyed, a raw pointer would be useless. If you do have insider insight then you can get a raw pointer originally - instead of the weak pointer - but the design of the weak pointer is intended to stop you accidentally getting one and creating unsafe code. Indeed, any such insight may be fragile in the face of medium/long-term evolution of the code, so it's probably better not to try to make such optimisations unless you absolutely must.
Perhaps an example of a good use of a weak pointer would help...
Say an object represents something on screen - if you want it to flash you add a weak pointer to a timer-driven flasher list then you can forget about it. When the timer next fires, if the Flasher code finds that object destroyed beforehand (i.e. it's not on screen any more) the flasher removes just it from the list, but it doesn't want to share ownership and keep the object around unnaturally. This might be easier than trying to have the code tracking when the object disappears from the screen having to tear it out from the flasher list (and potentially block waiting on a lock to do so).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With