Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::shared_ptr: reset() vs. assignment

This is a basic question, but I did not find a previous post about it. The title of the following question sounds like it might be the same question as mine, but the question itself does not match the title: is it better to use shared_ptr.reset or operator =?

I am confused about the purpose of the reset() member function of std::shared_ptr: what does it contribute in addition to the assignment operator?

To be concrete, given the definition:

auto p = std::make_shared<int>(1); 
  1. Are the following two lines equivalent:

    p = std::make_shared<int>(5); p.reset(new int(5)); 
  2. What about these:

    p = nullptr; p.reset(); 

If the two lines are equivalent in both cases, then what is the purpose of reset()?


EDIT: Let me re-phrase the question to better emphasize its point. The question is: is there a case where reset() lets us achieve something that is not as easily achievable without it?

like image 980
AlwaysLearning Avatar asked Jul 15 '15 18:07

AlwaysLearning


People also ask

What is the difference between Make_shared and shared_ptr?

The difference is that std::make_shared performs one heap-allocation, whereas calling the std::shared_ptr constructor performs two.

Should you use shared_ptr?

Use shared_ptr if you want to share ownership of a resource. Many shared_ptr can point to a single resource. shared_ptr maintains reference count for this propose. when all shared_ptr's pointing to resource goes out of scope the resource is destroyed.

What happens when shared_ptr goes out of scope?

All the instances point to the same object, and share access to one "control block" that increments and decrements the reference count whenever a new shared_ptr is added, goes out of scope, or is reset. When the reference count reaches zero, the control block deletes the memory resource and itself.

Do I have to delete shared_ptr?

The purpose of shared_ptr is to manage an object that no one "person" has the right or responsibility to delete, because there could be others sharing ownership. So you shouldn't ever want to, either.


2 Answers

When using reset() the parameter passed to reset need not be a managed object (nor can it be); whereas with = the right hand side must be a managed object.

So these two lines give you the same end result:

p = std::make_shared<int>(5); // assign to a newly created shared pointer p.reset(new int(5)); // take control of a newly created pointer 

But we cannot do:

p = new int(5); // compiler error no suitable overload p.reset(std::make_shared<int>(5).get()); // uh oh undefined behavior 

Without reset() you would not be able to reassign a shared pointer to a different raw pointer without creating a shared pointer and assigning it. Without = you wouldn't be able to make a shared pointer point to another shared pointer.

like image 160
NathanOliver Avatar answered Oct 02 '22 14:10

NathanOliver


It's possible for reset to avoid a dynamic memory allocation in certain cases. Consider the code

std::shared_ptr<int> p{new int{}};  // 1 p.reset(new int{});                 // 2 

On line 1 there are 2 dynamic memory allocations happening, one for the int object and a second one for the shared_ptr's control block that'll keep track of the number of strong/weak references to the managed object.

On line 2 there is again a dynamic memory allocation for a new int object. Within the body of reset the shared_ptr will determine that there are no other strong references to the previously managed int, so it must delete it. Since there aren't any weak references either, it could also deallocate the control block, but in this case it would be prudent for the implementation to reuse the same control block because it would otherwise have to allocate a new one anyway.

The above behavior would not be possible if you always had to use assignment.

std::shared_ptr<int> p{new int{}};    // 1 p = std::shared_ptr<int>{new int{}};  // 2 

In this case, the second call to the shared_ptr constructor on line 2 has already allocated a control block, so p will have to deallocate its own existing control block.

like image 21
Praetorian Avatar answered Oct 02 '22 14:10

Praetorian