Gewusst wie: Erstellen und Verwenden von unique_ptr-Instanzen
Der Zeiger eines unique_ptr-Objekts wird nicht freigegeben. Er kann nicht in ein anderes unique_ptr-Objekt kopiert, als Wert an eine Funktion übergeben oder in einem STL-Algorithmus (Standardvorlagenbibliothek) verwendet werden, für den Kopien erforderlich sind. Ein unique_ptr-Objekt kann nur verschoben werden. Dies bedeutet, dass der Besitz der Arbeitsspeicherressource einem anderen unique_ptr-Objekt übertragen wird und das ursprüngliche unique_ptr-Objekt diese Ressource nicht mehr besitzt. Es empfiehlt sich, ein Objekt auf einen Besitzer zu beschränken, da mehrere Besitzer die Komplexität der Programmlogik erhöhen. Wenn Sie einen intelligenten Zeiger für ein einfaches C++-Objekt benötigen, verwenden Sie daher unique_ptr. Wenn Sie ein unique_ptr-Objekt erstellen, verwenden Sie die make_unique-Hilfsfunktion.
Das folgende Diagramm veranschaulicht die Eigentumsübertragung zwischen zwei unique_ptr-Instanzen.
unique_ptr wird <memory>-Header in STL definiert. Das Objekt ist genau so effizient wie ein unformatierter Zeiger und kann in STL-Containern verwendet werden. Das Hinzufügen von unique_ptr-Instanzen zu STL-Containern ist effizient, da der Bewegungskonstruktor des unique_ptr-Objekts einen Kopiervorgang entfallen lässt.
Beispiel
Das folgende Beispiel zeigt, wie unique_ptr-Instanzen erstellt und zwischen Funktionen übergeben werden.
unique_ptr<Song> SongFactory(const std::wstring& artist, const std::wstring& title)
{
// Implicit move operation into the variable that stores the result.
return make_unique<Song>(artist, title);
}
void MakeSongs()
{
// Create a new unique_ptr with a new object.
auto song = make_unique<Song>(L"Mr. Children", L"Namonaki Uta");
// Use the unique_ptr.
vector<wstring> titles = { song->title };
// Move raw pointer from one unique_ptr to another.
unique_ptr<Song> song2 = std::move(song);
// Obtain unique_ptr from function that returns by value.
auto song3 = SongFactory(L"Michael Jackson", L"Beat It");
}
Diese Beispiele zeigen diese grundlegende Eigenschaft des unique_ptr-Objekts: Es kann verschoben, jedoch nicht kopiert werden. "Wird verschoben" überträgt den Besitz einem neuen unique_ptr-Objekt und setzt das alte unique_ptr-Objekt zurück.
Im folgenden Beispiel wird die Erstellung von unique_ptr-Instanzen und ihre Verwendung in einem Vektor dargestellt.
void SongVector()
{
vector<unique_ptr<Song>> songs;
// Create a few new unique_ptr<Song> instances
// and add them to vector using implicit move semantics.
songs.push_back(make_unique<Song>(L"B'z", L"Juice"));
songs.push_back(make_unique<Song>(L"Namie Amuro", L"Funky Town"));
songs.push_back(make_unique<Song>(L"Kome Kome Club", L"Kimi ga Iru Dake de"));
songs.push_back(make_unique<Song>(L"Ayumi Hamasaki", L"Poker Face"));
// Pass by const reference when possible to avoid copying.
for (const auto& song : songs)
{
wcout << L"Artist: " << song->artist << L" Title: " << song->title << endl;
}
}
Im Bereich der for-Schleife wird das unique_ptr-Objekt durch einen Verweis übergeben. Wenn Sie versuchen, das Objekt als Wert zu übergeben, löst der Compiler einen Fehler aus, da der unique_ptr-Kopierkonstruktor gelöscht wurde.
Das folgende Beispiel zeigt, wie ein unique_ptr-Objekt initialisiert wird, das ein Klassenmember ist.
class MyClass
{
private:
// MyClass owns the unique_ptr.
unique_ptr<ClassFactory> factory;
public:
// Initialize by using make_unique with ClassFactory default constructor.
MyClass() : factory ( make_unique<ClassFactory>())
{
}
void MakeClass()
{
factory->DoSomething();
}
};
Sie können make_unique zum Erstellen eines unique_ptr-Objekts für ein Array verwenden. Sie können make_unique jedoch nicht verwenden, um die Arrayelemente zu initialisieren.
// Create a unique_ptr to an array of 5 integers.
auto p = make_unique<int[]>(5);
// Initialize the array.
for (int i = 0; i < 5; ++i)
{
p[i] = i;
wcout << p[i] << endl;
}
Weitere Beispiele finden Sie unter make_unique.