If I understand correctly, a weak_ptr
doesn't increment the reference count of the managed object, therefore it doesn't represent ownership. It simply lets you access an object, the lifetime of which is managed by someone else.
So I don't really see why a weak_ptr
can't be constructed from a unique_ptr
, but only a shared_ptr
.
Can someone briefly explain this?
std::weak_ptr
can't be used unless you convert it tostd::shared_ptr
by the means oflock()
. if the standard allowed what you suggest, that means that you need to convert std::weak_ptr to unique in order to use it, violating the uniqueness (or re-inventingstd::shared_ptr
)In order to illustrate, look at the two pieces of code:
Now with your suggestion:
That has been said, you may suggest that there is only one
unique_ptr
, and you still can dereferenceweak_ptr
(without creating anotherunique_ptr
) then there is no problem. But then what is the difference betweenunique_ptr
andshared_ptr
with one reference? or more over, what is the difference between a regularunique_ptr
and C-pointers an get by usingget
?weak_ptr
is not for "general non owning resources", it has very specific job - The main goal ofweak_ptr
is to prevent circular pointing ofshared_ptr
which will make a memory leak. Anything else is pretty much need to be done with plainunique_ptr
andshared_ptr
.Looks like everyone is writing here about std::weak_ptr but not about weak poiner concept which I believe is what the author is asking for
I think that no one mentioned why standard library is not providing weak_ptr for unique_ptr. Weak pointer CONCEPT doesn't disclaims unique_ptr usage. Weak pointer is only an information if the object has been already deleted so it's not a magic but very simple generalized observer pattern.
It's because of threadsafety and consistency with shared_ptr.
You just simply can't guarantee that your weak_ptr (created from unique_ptr existing on other thread) will be not destroyed during calling method on pointed object. It's because weak_ptr needs to be consistent with std::shared_ptr which guarantee threadsafety. You can implement weak_ptr which works correctly with unique_ptr but only on the same thread - lock method will be unnecessary in this case. You can check chromium sources for base::WeakPtr and base::WeakPtrFactory - you can use it freely with unique_ptr. Chromium weak pointer code is most probably based on last member destruction - you need to add factory as a last member and after that I believe that WeakPtr is informed abut object deleteion (I'm not 100% sure) - so it doesn't looks so hard to implement.
Overall using unique_ptr with weak pointer concept is OK IMHO.
No-one has mentioned the performance aspect of the problem yet, so let me throw my $0.02 in.
weak_ptr
must somehow know when the correspondingshared_ptr
s have all gone out of scope and the pointed object has been deallocated and destroyed. This means thatshared_ptr
s need to communicate the destruction towards eachweak_ptr
to the same object somehow. This has a certain cost – for example, a global hash table needs to be updated, whereweak_ptr
gets the address from (ornullptr
if the object is destroyed).This also involves locking in a multi-threaded environment, so it can potentially be too slow for some tasks.
However, the goal of
unique_ptr
is to provide a zero-cost RAII-style abstraction class. Hence, it should not incur any other cost than that ofdelete
ing (ordelete[]
ing) the dynamically allocated object. The delay imposed by doing a locked or otherwise guarded hash table access, for example, may be comparable to the cost of deallocation, however, which is not desirable in the case ofunique_ptr
.It may be useful to distinguish reasons for preferring a
unique_ptr
over ashared_ptr
.Performance One obvious reason is computational-time and memory use. As currently defined,
shared_ptr
objects typically need something like a reference-count value, which takes space and also must be actively maintained.unique_ptr
objects don't.Semantics With a
unique_ptr
, you as the programmer have a pretty good idea when the pointed-to object is going to be destroyed: when theunique_ptr
is destroyed or when one of its modifying methods is called. And so on large or unfamiliar code bases, usingunique_ptr
statically conveys (and enforces) some information about the program's runtime behavior that might not be obvious.The comments above have generally focused on the performance-based reasons that it would be undesirable for
weak_ptr
objects to be tied tounique_ptr
objects. But one might wonder if the semantics-based argument is sufficient reason for some future version of the STL to support the use-case implied by the original question.Conceptually, there is nothing preventing an implementation where a weak_ptr only provides access and a unique_ptr controls the lifetime. However, there are problems with that:
unique_ptr
doesn't use reference counting to begin with. Adding the management structure for managing the weak references would be possible, but require an additional dynamic allocation. Sinceunique_ptr
is supposed to avoid any(!) runtime overhead over a raw pointer, that overhead is not acceptable.weak_ptr
, you need to extract a "real" reference from it, which will first validate that the pointer is not expired first and then give you this real reference (ashared_ptr
in this case). This means that you suddenly have a second reference to an object that is supposed to be uniquely owned, which is a recipe for errors. This can't be fixed by returning a mixed half-strong pointer that only temporarily delays possible destruction of the pointee, because you could just as well store that one, too, defeating the idea behindunique_ptr
.Just wondering, what problem are you trying to solve using a
weak_ptr
here?If you think about it, a
weak_ptr
must refer to something other than the object itself. That's because the object can cease to exist (when there are no more strong pointers to it) and theweak_ptr
still has to refer to something that contains the information that the object no longer exists.With a
shared_ptr
, that something is the thing that contains the reference count. But with aunique_ptr
, there is no reference count, so there is no thing that contains the reference count, thus nothing to continue to exist when the object is gone. So there's nothing for aweak_ptr
to refer to.There would also be no sane way to use such a
weak_ptr
. To use it, you'd have to have some way to guarantee that the object wasn't destroyed while you were using it. That's easy with ashared_ptr
-- that's what ashared_ptr
does. But how do you do that with aunique_ptr
? You obviously can't have two of them, and something else must already own the object or it would have been destroyed since your pointer is weak.