I understand that unique_ptr is a single owner of some object and it deallocates that object when it goes out of scope. What I don't understand is the following situation:
unique_ptr<int> p(new int(1));
p = unique_ptr<int>(new int(2));
What happens with the first object new int(1) if p is redirected to another memory location new int(2) (since p can own only one of those)?
A unique_ptr can only be moved. This means that the ownership of the memory resource is transferred to another unique_ptr and the original unique_ptr no longer owns it.
unique_ptr::resetReplaces the managed object. 1) Given current_ptr , the pointer that was managed by *this, performs the following actions, in this order: Saves a copy of the current pointer old_ptr = current_ptr. Overwrites the current pointer with the argument current_ptr = ptr.
std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.
But do remember that unique_ptr are there so that you don't have to manage directly the memory they hold. That is, you should know that a unique_ptr will safely delete its underlying raw pointer once it goes out of scope.
unique_ptr destroys the object it owns when the unique_ptr is destroyed or reseated. For example:
#include <iostream>
#include <memory>
using namespace std;
struct T {
T(int x) : x(x) {
cout << "T(" << x << ")\n";
}
~T() {
cout << "~T(" << x << ")\n";
}
int x;
};
int main() {
unique_ptr<T> p(new T(1));
p = unique_ptr<T>(new T(2));
}
This will print:
T(1) when the first object is created.T(2) when the second object is created.~T(1) when the first object is freed by the assignment operator of p.~T(2) when the second object is freed by the destructor of p.unique_ptr is defined to make sure the first int is properly deallocated, so it calls a delete on it, freeing the reserved memory.
It is somewhat identical to this code:
int* p = new int(1);
delete p;
p = new int(2);
What happens in detail is this:
new int(1).unique_ptr named p. This is an object that just stores the pointer for the moment.new int(2).unique_ptr using unique_ptr<int>(new int(2)), this is a temporary instance of unique_ptr (we will see why in a second) and it stores the pointer to the second int.p. Now the assignment operator is defined to delete the previously owned object (the first int) and take ownership of the object owned by the assigned unique_ptr (the second int). An implementation is shown below. At this point p owns the second int, the first int is deleted and the temporary owns no object anymore (holding the nullptr).unique_ptr goes out of scope, since we never gave it a name or stored a reference to it, so its destructor gets called. But it only holds the nullptr anyway.So the more detailed equivalent using raw pointers would be something like this:
int* p = new int(1); //create an int
{
int* tmp = new int(2); //create second int
int* del = p; //we need to delete this (first int)
//take ownership of the temporary (second int)
p = tmp;
tmp=nullptr;
//delete the old object (first int)
delete del;
} //tmp and del go out of scope here, but tmp holds the nullptr and del is deleted
//first int is deleted, p points to the second int here
Edit for Tracer:
This is the implementation used by visual studio (the comment is part of <memory> as well):
typedef unique_ptr<_Ty> _Myt;
_Myt& operator=(_Myt&& _Right) _NOEXCEPT
{ // assign by moving _Right
if (this != &_Right)
{ // different, do the move
reset(_Right.release());
this->get_deleter() = _STD forward<_Dx>(_Right.get_deleter());
}
return (*this);
}
void reset(pointer _Ptr = pointer()) _NOEXCEPT
{ // establish new pointer
pointer _Old = get();
this->_Myptr() = _Ptr;
if (_Old != pointer())
this->get_deleter()(_Old);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With