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