On 29/01/2016 23:25, Andrey Semashev wrote:
I think what Emil describes is a special case of a 'dangling_ptr' idiom, if I may call it that way. The point is that there are cases when object lifetime is controlled by a third party (e.g. the stack state, a foreign library, etc.) and you need a safe way to know when the object has been deleted. So you create a shared_ptr with a null_deleter pointing to that object and save it in that object (or another storage associated with that object). You keep only weak_ptrs to that object in all other places in the code. When you need to use the object you have to lock a weak_ptr and thus check if the object is still alive.
The thing is that there is rarely a case in practice where doing this is actually beneficial, unless you have a bit of code that *usually* deals with "real" shared_ptrs in the full shared-ownership sense and you want to exercise them in a context where you know they won't be used concurrently -- eg. unit tests. Typically single-threaded algorithms have a well-defined point at which the object is deleted (if this is a possibility), so it's not necessary to track this separately, and raw pointers/references are sufficient. (And if you're religiously opposed to having raw owning pointers, then use unique_ptr for the owning pointer and references for everything else.) We've already established that making a copy of the shared_ptr to be used outside the call chain (eg. by another thread, or just by this thread in a later operation) is obviously unsafe. Storing a weak_ptr in the single-threaded case is safe but pointless, as it should be obvious whether the object is alive or not during the initial operation (the code that deletes it can just store back a NULL, after all), and it will be guaranteed to be dead after that operation anyway. (This does assume that you have a known place to go to find that weak_ptr, rather than having lots of copies of it.) Storing a weak_ptr in the multi-threaded case is unsafe, because such code expects to be able to promote one to a shared_ptr during some operation and for the underlying object to not be deleted while that operation is in progress, the latter of which is violated when the lifetime is not controlled by the shared_ptr itself. It's that second aspect of weak_ptr -- the ability to promote to a shared_ptr and carry out operations secure in the knowledge that the object won't be surprise-deleted under you by concurrent action -- that many people seem to forget when discussions of wanting to use weak_ptr without shared ownership come up.