獨特的所有權(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 將失去所包含指標的所有權並且目標接收它。