独特的所有权(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_ptrstd::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_ptrvector 本身 - 是个人选择。

在 C++ 11 之前的版本中,std::auto_ptr 可用。与 unique_ptr 不同,它允许复制 auto_ptrs,源 ptr 将失去所包含指针的所有权并且目标接收它。