Procedura: Creare e utilizzare le istanze di shared_ptr
Il tipo di shared_ptr è un puntatore intelligente nella libreria standard di C++ progettata per gli scenari in cui più di un proprietario potrebbe essere necessario gestire la durata dell'oggetto in memoria.Dopo avere inizializzato shared_ptr che è possibile copiarlo, è necessario passarlo per valore negli argomenti della funzione e assegnarlo alle altre istanze di shared_ptr.Il punto di istanze gli stessi oggetti e condivide l'accesso a un "blocco di controllo" tale intervallo e diminuisce che il conteggio dei riferimenti ogni volta che il nuovo shared_ptr si aggiunge, area di validità, o viene reimpostato.Quando il conteggio dei riferimenti arriva a zero, il blocco di controllo elimina la risorsa di memoria e stessa.
Nella figura riportata più istanze di shared_ptr che indicano una posizione di memoria.
Esempio
Quando possibile, utilizzare la funzione di make_shared (<memory>) per creare shared_ptr quando la risorsa di memoria viene creata per la prima volta.make_shared è indipendente dalle eccezioni.Utilizza la stessa chiamata per allocare memoria per un blocco di controllo e la risorsa e si riduce l'overhead di costruzione.Se non si utilizza make_shared, è necessario utilizzare una nuova espressione esplicita per creare l'oggetto prima di procedere al costruttore di shared_ptr.Nell'esempio seguente vengono mostrati vari modi per dichiarare e inizializzare shared_ptr insieme a un nuovo oggetto.
// Use make_shared function when possible.
auto sp1 = make_shared<Song>(L"The Beatles", L"Im Happy Just to Dance With You");
// Ok, but slightly less efficient.
// Note: Using new expression as constructor argument
// creates no named variable for other code to access.
shared_ptr<Song> sp2(new Song(L"Lady Gaga", L"Just Dance"));
// When initialization must be separate from declaration, e.g. class members,
// initialize with nullptr to make your programming intent explicit.
shared_ptr<Song> sp5(nullptr);
//Equivalent to: shared_ptr<Song> sp5;
//...
sp5 = make_shared<Song>(L"Elton John", L"I'm Still Standing");
Di seguito viene illustrato come dichiarare e inizializzare le istanze di shared_ptr che hanno proprietà condivisa di un oggetto che è già stato allocato da un altro shared_ptr.Si supponga che sp2 è shared_ptrinizializzato.
//Initialize with copy constructor. Increments ref count.
auto sp3(sp2);
//Initialize via assignment. Increments ref count.
auto sp4 = sp2;
//Initialize with nullptr. sp7 is empty.
shared_ptr<Song> sp7(nullptr);
// Initialize with another shared_ptr. sp1 and sp2
// swap pointers as well as ref counts.
sp1.swap(sp2);
shared_ptr è utile anche nei contenitori standard di (STL) la libreria di modelli quando si utilizza algoritmi la copia gli elementi.È possibile eseguire il wrapping degli elementi in shared_ptrquindi copiarlo in altri contenitori fatto salvo che la memoria sottostante è valida fino a quando la si necessita e così via.Di seguito viene illustrato come utilizzare l'algoritmo di replace_copy_if su shared_ptr l'in un vettore.
vector<shared_ptr<Song>> v;
v.push_back(make_shared<Song>(L"Bob Dylan", L"The Times They Are A Changing"));
v.push_back(make_shared<Song>(L"Aretha Franklin", L"Bridge Over Troubled Water"));
v.push_back(make_shared<Song>(L"Thal�a", L"Entre El Mar y Una Estrella"));
vector<shared_ptr<Song>> v2;
remove_copy_if(v.begin(), v.end(), back_inserter(v2), [] (shared_ptr<Song> s)
{
return s->artist.compare(L"Bob Dylan") == 0;
});
for_each(v2.begin(), v2.end(), [] (shared_ptr<Song> s)
{
wcout << s->artist << L":" << s->title << endl;
});
È possibile utilizzare dynamic_pointer_cast, static_pointer_caste const_pointer_cast per eseguire il cast shared_ptr.Queste funzioni sono simili a dynamic_cast, a static_caste operatori di const_cast.Di seguito viene illustrato come verificare il tipo derivato di ogni elemento in un vettore di shared_ptr delle classi di base e quindi copiare elementi e visualizzare informazioni su di essi.
vector<shared_ptr<MediaAsset>> assets;
assets.push_back(shared_ptr<Song>(new Song(L"Himesh Reshammiya", L"Tera Surroor")));
assets.push_back(shared_ptr<Song>(new Song(L"Penaz Masani", L"Tu Dil De De")));
assets.push_back(shared_ptr<Photo>(new Photo(L"2011-04-06", L"Redmond, WA", L"Soccer field at Microsoft.")));
vector<shared_ptr<MediaAsset>> photos;
copy_if(assets.begin(), assets.end(), back_inserter(photos), [] (shared_ptr<MediaAsset> p) -> bool
{
// Use dynamic_pointer_cast to test whether
// element is a shared_ptr<Photo>.
shared_ptr<Photo> temp = dynamic_pointer_cast<Photo>(p);
return temp.get() != nullptr;
});
for_each(photos.begin(), photos.end(), [] (shared_ptr<MediaAsset> p)
{
// We know that the photos vector contains only
// shared_ptr<Photo> objects, so use static_cast.
wcout << "Photo location: " << (static_pointer_cast<Photo>(p))->location_ << endl;
});
È possibile passare shared_ptr a un'altra funzione nei modi seguenti:
Passare shared_ptr per valore.In questo modo viene richiamato il costruttore di copia, incrementa il conteggio dei riferimenti e rende il computer denominato proprietario.Esiste una piccola quantità di sovraccarico in questa operazione, che può essere significativa base al numero di oggetti di shared_ptr si stanno passando.Utilizzare questa opzione quando il contratto di codice (implicito o esplicito) tra il chiamante e il chiamato richiede che il chiamato sia un proprietario.
Passare shared_ptr per riferimento o per riferimento const.In questo caso, il conteggio dei riferimenti non viene incrementato e il chiamato può accedere al puntatore fino a quando il chiamante non area di validità.O, il quale può decidere di creare shared_ptr base al riferimento e pertanto di diventare un proprietario condiviso.Utilizzare questa opzione quando il chiamante non contiene alcuna informazione del chiamato, o se è necessario passare shared_ptr e si desidera evitare l'operazione di copia per motivi di prestazioni.
Passare il puntatore sottostante o un riferimento all'oggetto sottostante.Ciò consente al chiamato per utilizzare l'oggetto, ma non lo consente di condividere la proprietà o estende la durata.Se il computer denominato crea shared_ptr il puntatore non elaborato, tornare shared_ptr è indipendente dall'originale e non controlla la risorsa sottostante.Utilizzare questa opzione quando il contratto tra il chiamante e il chiamato specifica chiarito che il chiamante deve mantenere la proprietà della durata di shared_ptr.
Quando si decidere come passare shared_ptr, determinare se il chiamato deve condividere la proprietà della risorsa sottostante."Un proprietario" è un oggetto o una funzione che può mantenere la risorsa sottostante attivo fino a quando la necessità.Se il chiamante deve garantire che il chiamato può prolungare la durata del puntatore sulla durata (la funzione), utilizzare la prima opzione.Se non è necessario stabilire se il chiamato estende la durata, la sessione per riferimento e consentire al chiamato copiarla o meno.
Se è necessario fornire un accesso di una funzione di supporto al puntatore sottostante e sa che una funzione di supporto utilizzerà solo il puntatore e tornare prima che la funzione chiamante, pertanto la funzione non deve condividere la proprietà del puntatore sottostante.Deve accedere solo il puntatore sulla durata di shared_ptrdel chiamante.In questo caso, è possibile passare shared_ptr per riferimento, o passare il puntatore non elaborato o un riferimento all'oggetto sottostante.Passare questo metodo fornisce un piccolo miglioramento delle prestazioni e può inoltre consentire di esprimere lo scopo di programmazione.
Talvolta, ad esempio in std:vector<shared_ptr<T>>, è possibile dovere passare ogni shared_ptr un corpo di un'espressione lambda o a un oggetto funzione denominato.Se la funzione lambda o non memorizza il puntatore, quindi passare shared_ptr con riferimento all'evitare a richiamare il costruttore di copia per ogni elemento.
Di seguito viene illustrato come shared_ptr esegue l'overload di alcuni operatori di confronto per abilitare i confronti del puntatore sulla memoria è posseduta da shared_ptr un'istanza.
// Initialize two separate raw pointers.
// Note that they contain the same values.
auto song1 = new Song(L"Village People", L"YMCA");
auto song2 = new Song(L"Village People", L"YMCA");
// Create two unrelated shared_ptrs.
shared_ptr<Song> p1(song1);
shared_ptr<Song> p2(song2);
// Unrelated shared_ptrs are never equal.
wcout << "p1 < p2 = " << std::boolalpha << (p1 < p2) << endl;
wcout << "p1 == p2 = " << std::boolalpha <<(p1 == p2) << endl;
// Related shared_ptr instances are always equal.
shared_ptr<Song> p3(p2);
wcout << "p3 == p2 = " << std::boolalpha << (p3 == p2) << endl;