重定向 unique_ptr 时会发生什么?
What happens when redirecting unique_ptr?
我知道 unique_ptr
是某个对象的单一所有者,当它超出范围时它会释放该对象。我不明白的是以下情况:
unique_ptr<int> p(new int(1));
p = unique_ptr<int>(new int(2));
如果 p
被重定向到另一个内存位置 new int(2)
(因为 p
只能拥有其中一个),第一个对象 new int(1)
会发生什么情况?
unique_ptr
被定义为确保第一个 int 被正确释放,因此它在其上调用 delete
,释放保留的内存。
它与此代码有些相同:
int* p = new int(1);
delete p;
p = new int(2);
详细情况是这样的:
- 您使用
new int(1)
创建了一个新的整数。
- 您将指向此新 int 的指针传递给刚刚创建的名为
p
的 unique_ptr
实例。这是一个暂时只存储指针的对象。
- 您使用
new int(2)
创建第二个 int。
- 您使用
unique_ptr<int>(new int(2))
将此指针传递给新的 unique_ptr
,这是 unique_ptr 的临时实例(我们稍后会看到原因)并将指针存储到第二个整数。
- 您将临时对象分配给
p
。现在赋值运算符被定义为删除以前拥有的对象(第一个 int)并获得分配的 unique_ptr(第二个 int)所拥有的对象的所有权。一个实现如下所示。此时 p
拥有第二个 int,第一个 int 被删除,临时对象不再拥有任何对象(持有 nullptr
)。
- 作为最后一部分,临时
unique_ptr
超出了范围,因为我们从未给它命名或存储对它的引用,所以它的析构函数被调用。但无论如何它只包含 nullptr
。
所以更详细的使用原始指针的等价物是这样的:
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
为 Tracer 编辑:
这是 visual studio 使用的实现(注释也是 <memory>
的一部分):
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);
}
unique_ptr
在 unique_ptr
被销毁 或重新安装 时销毁它拥有的对象。例如:
#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));
}
这将打印:
T(1)
创建第一个对象时。
T(2)
当创建第二个对象时。
~T(1)
当第一个对象被 p
. 的赋值运算符释放时
~T(2)
当第二个对象被 p
. 的析构函数释放时
我知道 unique_ptr
是某个对象的单一所有者,当它超出范围时它会释放该对象。我不明白的是以下情况:
unique_ptr<int> p(new int(1));
p = unique_ptr<int>(new int(2));
如果 p
被重定向到另一个内存位置 new int(2)
(因为 p
只能拥有其中一个),第一个对象 new int(1)
会发生什么情况?
unique_ptr
被定义为确保第一个 int 被正确释放,因此它在其上调用 delete
,释放保留的内存。
它与此代码有些相同:
int* p = new int(1);
delete p;
p = new int(2);
详细情况是这样的:
- 您使用
new int(1)
创建了一个新的整数。 - 您将指向此新 int 的指针传递给刚刚创建的名为
p
的unique_ptr
实例。这是一个暂时只存储指针的对象。 - 您使用
new int(2)
创建第二个 int。 - 您使用
unique_ptr<int>(new int(2))
将此指针传递给新的unique_ptr
,这是 unique_ptr 的临时实例(我们稍后会看到原因)并将指针存储到第二个整数。 - 您将临时对象分配给
p
。现在赋值运算符被定义为删除以前拥有的对象(第一个 int)并获得分配的 unique_ptr(第二个 int)所拥有的对象的所有权。一个实现如下所示。此时p
拥有第二个 int,第一个 int 被删除,临时对象不再拥有任何对象(持有nullptr
)。 - 作为最后一部分,临时
unique_ptr
超出了范围,因为我们从未给它命名或存储对它的引用,所以它的析构函数被调用。但无论如何它只包含nullptr
。
所以更详细的使用原始指针的等价物是这样的:
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
为 Tracer 编辑:
这是 visual studio 使用的实现(注释也是 <memory>
的一部分):
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);
}
unique_ptr
在 unique_ptr
被销毁 或重新安装 时销毁它拥有的对象。例如:
#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));
}
这将打印:
T(1)
创建第一个对象时。T(2)
当创建第二个对象时。~T(1)
当第一个对象被p
. 的赋值运算符释放时
~T(2)
当第二个对象被p
. 的析构函数释放时