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