Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't a weak_ptr be constructed from a unique_ptr?

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?

like image 784
notadam Avatar asked Mar 15 '15 09:03

notadam


People also ask

Why would you choose shared_ptr instead of unique_ptr?

In short: Use unique_ptr when you want a single pointer to an object that will be reclaimed when that single pointer is destroyed. Use shared_ptr when you want multiple pointers to the same resource.

What happens when unique_ptr goes out of scope?

unique_ptr. An​ unique_ptr has exclusive ownership of the object it points to and ​will destroy the object when the pointer goes out of scope.

What is the difference between Auto_ptr and unique_ptr?

unique_ptr is a new facility with a similar functionality, but with improved security. auto_ptr is a smart pointer that manages an object obtained via new expression and deletes that object when auto_ptr itself is destroyed.

Can weak_ptr be copied?

std::weak_ptr are pointers, so as with any pointer types, a = p; copy pointer, not the content of what is pointed. If you want to copy the content, you would need *a = *p; , but you cannot do that with weak_ptr , you need to lock() both a and p before.

Why do we use weak pointers instead of 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.

Can there be a weak_ptr without a shared_ptr?

tl;dr; weak_ptr depends on a weak reference count which is part of shared_ptr, there cannot be a weak_ptr without a shared_ptr. In effect, a weak_ptr is a shared_ptr to the reference count object. Conceptually, there is nothing preventing an implementation where a weak_ptr only provides access and a unique_ptr controls the lifetime.

What is weak_ptr in C++?

A weak_ptr is created as a copy of shared_ptr. It provides access to an object that is owned by one or more shared_ptr instances but does not participate in reference counting. The existence or destruction of weak_ptr has no effect on the shared_ptr or its other copies.

Why do we need a separate stored pointer for shared_ptr?

the stored pointer of the shared_ptr it was constructed from. A separate stored pointer is necessary to ensure that converting a shared_ptr to weak_ptr and then back works correctly, even for aliased shared_ptr s. It is not possible to access the stored pointer in a weak_ptr without locking it into a shared_ptr .


2 Answers

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 the weak_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 a unique_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 a weak_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 a shared_ptr -- that's what a shared_ptr does. But how do you do that with a unique_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.

like image 107
David Schwartz Avatar answered Oct 23 '22 16:10

David Schwartz


std::weak_ptr can't be used unless you convert it to std::shared_ptr by the means of lock(). 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-inventing std::shared_ptr)

In order to illustrate, look at the two pieces of code:

std::shared_ptr<int> shared = std::make_shared<int>(10);
std::weak_ptr<int> weak(shared);

{
*(weak.lock()) = 20; //OK, the temporary shared_ptr will be destroyed but the pointee-integer still has shared  to keep it alive
}

Now with your suggestion:

std::unique_ptr<int> unique = std::make_unique<int>(10);
std::weak_ptr<int> weak(unique);

{
*(weak.lock()) = 20; //not OK. the temporary unique_ptr will be destroyed but unique still points at it! 
}

That has been said, you may suggest that there is only one unique_ptr, and you still can dereference weak_ptr (without creating another unique_ptr) then there is no problem. But then what is the difference between unique_ptr and shared_ptr with one reference? or moreover, what is the difference between a regular unique_ptr and C-pointers an get by using get?

weak_ptr is not for "general nonowning resources", it has a very specific job - The main goal of weak_ptr is to prevent circular pointing of shared_ptr which will make a memory leak. Anything else needs to be done with plain unique_ptr and shared_ptr.

like image 29
David Haim Avatar answered Oct 23 '22 14:10

David Haim