Vorgehensweise: Erstellen und Verwenden von unique_ptr-Instanzen

Ein unique_ptr teilt seinen Zeiger nicht. Sie kann nicht in einen anderen unique_ptrkopiert werden, der von einem Wert an eine Funktion übergeben wird oder in einem beliebigen C++-Standardbibliotheksalgorithmus verwendet wird, der Kopien erstellen muss. 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_ptrSie unique_ptrdie hilfsfunktion make_unique.

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

Diagram that shows moving the ownership of a unique pointer.

unique_ptr wird in der <memory> Kopfzeile in der C++-Standardbibliothek definiert. Es ist genau so effizient wie ein unformatierter Zeiger und kann in C++-Standardbibliothekscontainern verwendet werden. Das Hinzufügen von unique_ptr Instanzen zu C++-Standardbibliothekscontainern ist effizient, da der Verschiebungskonstruktor der unique_ptr Notwendigkeit eines Kopiervorgangs beseitigt wird.

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 Array zu erstellen, aber Sie können die Arrayelemente nicht make_unique 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