如果我取一个unique_ptr的原始指针,然后使用reset,是否仍然保证原始指针有效?
If I take a raw pointer of a unique_ptr and then use reset, is the raw pointer still guaranteed to be valid?
例如,我很确定这行得通。
int foo = 51;
int* bar = &foo;
foo = 3;
所以bar仍然有效,并且*bar == 3
。
如果我们说
std::unique_ptr<int> foo(new int(51)); // should probably use make_unique
int* bar = foo.get();
foo.reset(new int(3));
我能保证*bar == 3
吗?
还是我继续引用 bar 导致了未定义的行为?
不,一点也不。你会得到未定义的行为,因为 unique_ptr
管理的原始指针被 reset
改变了。事实上,unique_ptr
删除了托管指针并重新分配了一个新指针,因此您的旧指针将继续指向旧地址,该地址不再有效。您的代码等同于:
#include <iostream>
int main()
{
int* managed = new int(51); // equivalent to unique_ptr(new int(51));
int* bar = managed; // equivalent of unique_ptr::get
delete managed; managed = new int(3); // equivalent to unique_ptr::reset(new int(3))
std::cout << *bar << std::endl; // Wrong!!! Undefined behaviour, bar is dangling!
}
你的第一个代码片段确实是正确的,因为你没有改变那里的任何地址,你只是改变了指针指向的变量,所以当然取消引用指针会得到更新的值。
不,如果你重置一个unique_ptr
,它会删除它拥有的指针。
你可以这样做:
int* bar = foo.release();
这导致 foo
放弃其指针的所有权并 return 它。
否,std::unique_ptr.reset 将删除现有指针。
见http://www.cplusplus.com/reference/memory/unique_ptr/reset/
为了您的目的,请使用 release。
例如,我很确定这行得通。
int foo = 51;
int* bar = &foo;
foo = 3;
所以bar仍然有效,并且*bar == 3
。
如果我们说
std::unique_ptr<int> foo(new int(51)); // should probably use make_unique
int* bar = foo.get();
foo.reset(new int(3));
我能保证*bar == 3
吗?
还是我继续引用 bar 导致了未定义的行为?
不,一点也不。你会得到未定义的行为,因为 unique_ptr
管理的原始指针被 reset
改变了。事实上,unique_ptr
删除了托管指针并重新分配了一个新指针,因此您的旧指针将继续指向旧地址,该地址不再有效。您的代码等同于:
#include <iostream>
int main()
{
int* managed = new int(51); // equivalent to unique_ptr(new int(51));
int* bar = managed; // equivalent of unique_ptr::get
delete managed; managed = new int(3); // equivalent to unique_ptr::reset(new int(3))
std::cout << *bar << std::endl; // Wrong!!! Undefined behaviour, bar is dangling!
}
你的第一个代码片段确实是正确的,因为你没有改变那里的任何地址,你只是改变了指针指向的变量,所以当然取消引用指针会得到更新的值。
不,如果你重置一个unique_ptr
,它会删除它拥有的指针。
你可以这样做:
int* bar = foo.release();
这导致 foo
放弃其指针的所有权并 return 它。
否,std::unique_ptr.reset 将删除现有指针。
见http://www.cplusplus.com/reference/memory/unique_ptr/reset/
为了您的目的,请使用 release。