How to: 建立和使用 unique_ptr 執行個體
A unique_ptr不會共用它的指標。 不能複製到另一個unique_ptr,傳值方式傳遞至函式 (除非它是可修改的右值),或設成可複製所需的任何標準樣板程式庫 (STL) 演算法中使用。 A unique_ptr只能移動。 這表示將記憶體資源的擁有權轉移到新unique_ptr和原本unique_ptr不再擁有它。 我們建議您限制物件只能在一個擁有者,因為多個擁有權的程式邏輯會增加複雜性。 因此,當您需要的智慧型指標為一般的 C++ 物件時,使用unique_ptr。
下圖說明兩個之間的擁有權轉移unique_ptr執行個體。
unique_ptr定義在<memory> STL 中的標頭。 它是完全有效做為未經處理的指標,並且能在 STL 容器中。 額外的unique_ptr執行個體 STL 容器會有效率因為移動建構函式的unique_ptr就不需要複製作業。
範例
下列範例示範如何建立unique_ptr執行個體,並將其傳遞函數之間。
unique_ptr<Song> SongFactory(std::wstring artist, std::wstring title)
{
// Implicit move operation into the variable that stores the result.
return unique_ptr<Song>(new Song(artist, title));
}
void MakeSongs()
{
// Create a new unique_ptr with a new object.
unique_ptr<Song> pSong = unique_ptr<Song>(new Song(L"Mr. Children", L"Namonaki Uta"));
// Use the unique_ptr
vector<wstring> titles;
titles.push_back(pSong->title);
// Move raw pointer from one unique_ptr to another.
unique_ptr<Song> pSong2 = std::move(pSong);
// Obtain unique_ptr from function that returns rvalue reference.
auto pSong3 = SongFactory(L"Michael Jackson", L"Beat It");
}
這些範例說明的基本特質unique_ptr: 移動,但不是會複製。「 移動"將轉移到新的擁有權unique_ptr ,並將舊的unique_ptr。
下列範例示範如何建立unique_ptr執行個體,並將它們運用於向量。
void SongVector()
{
vector<unique_ptr<Song>> v;
// Create a few new unique_ptr<Song> instances
// and add them to vector using implicit move semantics.
v.push_back(unique_ptr<Song>(new Song(L"B'z", L"Juice")));
v.push_back(unique_ptr<Song>(new Song(L"Namie Amuro", L"Funky Town")));
v.push_back(unique_ptr<Song>(new Song(L"Kome Kome Club", L"Kimi ga Iru Dake de")));
v.push_back(unique_ptr<Song>(new Song(L"Ayumi Hamasaki", L"Poker Face")));
// Pass by reference to lambda body.
for_each(v.begin(), v.end(), [] (const unique_ptr<Song>& p)
{
wcout << L"Artist: " << p->artist << L"Title: " << p->title << endl;
});
}
在for_each循環播放,請注意, unique_ptr已經傳遞 lambda 運算式中的參考。 如果您嘗試以傳值方式傳遞,編譯器會擲回錯誤因為unique_ptr已停用複製建構函式。
下列範例示範如何初始化unique_ptr也就是類別成員。
class MyClass
{
private:
// MyClass owns the unique_ptr.
unique_ptr<ClassFactory> factory;
public:
// Initialize by invoking the unique_ptr move constructor.
MyClass() : factory ( unique_ptr<ClassFactory>(new ClassFactory()))
{
}
void MakeClass()
{
factory->DoSomething();
}
};