std::shared_ptr: reset() vs. assignment
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.
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.