Vorgehensweise: Erstellen und Verwenden von unique_ptr-Instanzen

Ein unique_ptr gibt seinen Zeiger nicht frei. Sie kann nicht in ein anderes kopiert, unique_ptr als Wert an eine Funktion übergeben oder in einem C++-Standardbibliotheksalgorithmus verwendet werden, für den Kopien erstellt werden müssen. 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 daher einen intelligenten Zeiger für ein einfaches C++-Objekt benötigen, verwenden unique_ptr Sie , und wenn Sie eine unique_ptr erstellen, verwenden Sie die make_unique Hilfsfunktion.

Das folgende Diagramm veranschaulicht die Eigentumsübertragung zwischen zwei unique_ptr-Instanzen.

Verschieben des Besitzes eines eindeutigen_ptr.

unique_ptr wird im <memory> Header in der C++-Standardbibliothek definiert. Er ist genau so effizient wie ein roher Zeiger und kann in C++-Standardbibliothekscontainern verwendet werden. Das Hinzufügen von unique_ptr Instanzen zu C++-Standardbibliothekscontainern ist effizient, da der Verschiebungskonstruktor von unique_ptr die Notwendigkeit eines Kopiervorgangs entfällt.

Beispiel 1

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.

Beispiel 2

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.

Beispiel 3

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();
    }
};

Beispiel 4

Sie können make_unique verwenden, um ein unique_ptr in einem Array zu erstellen, aber Sie können nicht make_unique 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.

Siehe auch

Intelligente Zeiger (Modern C++)
make_unique