独特的所有权(stdunique ptr)
Version >= C++ 11
一个 std::unique_ptr
是管理动态存储的对象的生存期类模板。与 std::shared_ptr
不同,动态对象在任何时候都只由 std::unique_ptr
的一个实例拥有,
// Creates a dynamic int with value of 20 owned by a unique pointer
std::unique_ptr<int> ptr = std::make_unique<int>(20);
(注意:从 C++ 11 开始,std::unique_ptr
可用,自 C++ 14 以来,std::make_unique
可用。)
只有变量 ptr
拥有一个指向动态分配的 int
的指针。当拥有对象的唯一指针超出范围时,将删除拥有的对象,即如果对象是类类型,则调用其析构函数,并释放该对象的内存。
要将 std::unique_ptr
和 std::make_unique
与数组类型一起使用,请使用它们的数组特化:
// Creates a unique_ptr to an int with value 59
std::unique_ptr<int> ptr = std::make_unique<int>(59);
// Creates a unique_ptr to an array of 15 ints
std::unique_ptr<int[]> ptr = std::make_unique<int[]>(15);
你可以像原始指针一样访问 std::unique_ptr
,因为它会使这些运算符超载。
你可以使用 std::move
将智能指针内容的所有权转移到另一个指针,这将导致原始智能指针指向 nullptr
。
// 1. std::unique_ptr
std::unique_ptr<int> ptr = std::make_unique<int>();
// Change value to 1
*ptr = 1;
// 2. std::unique_ptr (by moving 'ptr' to 'ptr2', 'ptr' doesn't own the object anymore)
std::unique_ptr<int> ptr2 = std::move(ptr);
int a = *ptr2; // 'a' is 1
int b = *ptr; // undefined behavior! 'ptr' is 'nullptr'
// (because of the move command above)
将 unique_ptr
传递给函数作为参数:
void foo(std::unique_ptr<int> ptr)
{
// Your code goes here
}
std::unique_ptr<int> ptr = std::make_unique<int>(59);
foo(std::move(ptr))
从功能中返回 unique_ptr
。这是编写工厂函数的首选 C++ 11 方式,因为它清楚地传达了返回的所有权语义:调用者拥有生成的 unique_ptr
并负责它。
std::unique_ptr<int> foo()
{
std::unique_ptr<int> ptr = std::make_unique<int>(59);
return ptr;
}
std::unique_ptr<int> ptr = foo();
比较这个:
int* foo_cpp03();
int* p = foo_cpp03(); // do I own p? do I have to delete it at some point?
// it's not readily apparent what the answer is.
Version < C++ 14
从 C++ 14 开始提供类模板 make_unique
。将它手动添加到 C++ 11 代码很容易:
template<typename T, typename... Args>
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(Args&&... args)
{ return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); }
// Use make_unique for arrays
template<typename T>
typename std::enable_if<std::is_array<T>::value, std::unique_ptr<T>>::type
make_unique(size_t n)
{ return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]()); }
Version >= C++ 11
与哑智能指针(std::auto_ptr
)不同,unique_ptr
也可以用矢量分配实例化( 不是 std::vector
)。早期的例子是标量分配。例如,要为 10 个元素提供动态分配的整数数组,你可以将 int[]
指定为模板类型(而不仅仅是 int
):
std::unique_ptr<int[]> arr_ptr = std::make_unique<int[]>(10);
哪个可以简化:
auto arr_ptr = std::make_unique<int[]>(10);
现在,你使用 arr_ptr
就好像它是一个数组:
arr_ptr[2] = 10; // Modify third element
你无需担心取消分配。此模板专用版本适当地调用构造函数和析构函数。使用矢量版 unique_ptr
或 vector
本身 - 是个人选择。
在 C++ 11 之前的版本中,std::auto_ptr
可用。与 unique_ptr
不同,它允许复制 auto_ptr
s,源 ptr
将失去所包含指针的所有权并且目标接收它。