Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't weak pointers access the underlying pointer?

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?

like image 481
quant Avatar asked Jun 23 '13 23:06

quant


2 Answers

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.

like image 171
Rob Kennedy Avatar answered Oct 19 '22 03:10

Rob Kennedy


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

like image 33
Tony Delroy Avatar answered Oct 19 '22 01:10

Tony Delroy