Condividi tramite


Procedura: creare e utilizzare istanze unique_ptr

unique_ptr non condivide il puntatore. Non può essere copiato in un altro unique_ptr, passato per valore a una funzione o utilizzato in qualsiasi algoritmo della libreria STL (Standard Template Library) che richiede l'esecuzione di copie. È possibile solo spostare un oggetto unique_ptr. Ciò significa che la proprietà della risorsa di memoria viene trasferita a un altro unique_ptr e l'oggetto unique_ptr originale non è più proprietario della risorsa. Si consiglia di limitare un oggetto a un solo proprietario, poiché la proprietà multipla rende più complessa la logica del programma. Pertanto, quando è necessario un puntatore intelligente per un oggetto C++ normale, utilizzare unique_ptr e quando si costruisce un oggetto unique_ptr, utilizzare la funzione di supporto make_unique.

Nel diagramma seguente è illustrato il passaggio di proprietà tra due istanze di unique_ptr.

Trasferimento della proprietà di unique_ptr

unique_ptr viene definito nell'intestazione <memory> della libreria STL. È esattamente efficiente quanto il puntatore non elaborato e può essere utilizzato nei contenitori STL. L'aggiunta di istanze di unique_ptr ai contenitori STL è efficace poiché il costruttore di spostamento di unique_ptr elimina la necessità di un'operazione di copia.

Esempio

Nell'esempio seguente viene illustrato come creare istanze di unique_ptr e passarle tra funzioni.

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

In questi esempi viene illustrata la caratteristica di base di unique_ptr, che può essere spostato, ma non copiato. Lo spostamento ("move") trasferisce la proprietà a un nuovo oggetto unique_ptr e reimposta l'oggetto unique_ptrprecedente.

Nell'esempio seguente viene illustrato come creare istanze di unique_ptr e utilizzarle in un vettore.

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

Nell'intervallo per il ciclo, si noti che unique_ptr viene passato per riferimento. Se si tenta di passare per valore, il compilatore genererà un errore perché il costruttore di copia unique_ptr viene eliminato.

Nell'esempio seguente viene illustrato come inizializzare un unique_ptr che è un membro di classe.

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

È possibile utilizzare make_unique per creare unique_ptr in una matrice, ma non è possibile utilizzare make_unique per inizializzare gli elementi della matrice.

   // 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;
    }

Per ulteriori esempi, vedere make_unique.

Vedere anche

Riferimenti

make_unique

Concetti

Puntatori intelligenti (C++ moderno)