Il mondo in cui vive Bjarne è molto ... accademico, per mancanza di un termine migliore. Se il tuo codice può essere progettato e strutturato in modo tale che gli oggetti abbiano gerarchie relazionali molto deliberate, in modo tale che le relazioni di proprietà siano rigide e inflessibili, il codice scorre in una direzione (da alto a basso) e gli oggetti parlano solo a quelli più bassi la gerarchia, quindi non troverai molto bisogno di shared_ptr
. È qualcosa che usi in quelle rare occasioni in cui qualcuno deve infrangere le regole. In caso contrario, puoi semplicemente inserire tutto in vector
s o altre strutture dati che utilizzano la semantica del valore e unique_ptr
s per le cose che devi allocare singolarmente.
Mentre quello è un grande mondo in cui vivere, non è quello che si fa a fare tutto il tempo. Se non puoi organizzare il tuo codice in quel modo, perché il design del sistema che stai cercando di rendere significa che è impossibile (o semplicemente spiacevole), allora ti troverai proprietà condivisa di oggetti sempre di più.
In un sistema del genere, tenere puntatori nudi non ... è pericoloso esattamente, ma solleva domande. Il bello di shared_ptr
è che fornisce garanzie ematiche ragionevoli sulla durata dell'oggetto. Può essere rotto? Ovviamente. Ma le persone possono anche const_cast
di cose; l'assistenza di base e l'alimentazione di shared_ptr
dovrebbero fornire una ragionevole qualità di vita per gli oggetti allocati a cui deve essere condivisa la proprietà.
Quindi, ci sono weak_ptr
s, che non possono essere utilizzati in assenza di shared_ptr
. Se il tuo sistema è rigidamente strutturato, puoi memorizzare un puntatore nudo su un oggetto, sicuro sapendo che la struttura dell'applicazione garantisce che l'oggetto puntato sopravviverà a te. È possibile chiamare una funzione che restituisce un puntatore a un valore interno o esterno (trovare l'oggetto denominato X, ad esempio). Nel codice correttamente strutturato, tale funzione sarebbe disponibile solo se la durata dell'oggetto fosse garantita per superare il proprio; quindi, conservare quel puntatore nudo nel tuo oggetto va bene.
Poiché questa rigidità non è sempre possibile ottenere nei sistemi reali, è necessario un modo per garantire ragionevolmente la durata. A volte, non hai bisogno di piena proprietà; a volte, devi solo essere in grado di sapere quando il puntatore è cattivo o buono. Ecco dove arriva weak_ptr
. Ci sono stati casi in cui I potrebbe aver usato un unique_ptr
o boost::scoped_ptr
, ma ho dovuto usare un shared_ptr
perché I specificamente necessario per dare a qualcuno un puntatore "volatile". Un puntatore che è a vita era indeterminato e potevano interrogare quando quel puntatore veniva distrutto.
Un modo sicuro per sopravvivere quando lo stato del mondo è indeterminato.
Potrebbe essere stato fatto da qualche chiamata di funzione per ottenere il puntatore, invece che tramite weak_ptr
? Sì, ma potrebbe essere più facilmente infranto. Una funzione che restituisce un puntatore nudo non ha modo di suggerire sintatticamente che l'utente non faccia qualcosa come memorizzare quel puntatore a lungo termine. Restituire un shared_ptr
rende inoltre troppo facile per qualcuno semplicemente memorizzarlo e potenzialmente prolungare la durata di vita di un oggetto. Restituire un weak_ptr
tuttavia suggerisce strongmente che l'archiviazione del shared_ptr
ottenuto da lock
è un'idea ... dubbiosa. Non ti impedirà di farlo, ma nulla in C ++ ti impedisce di rompere il codice. weak_ptr
fornisce una minima resistenza dal fare la cosa naturale.
Ora, questo non vuol dire che shared_ptr
non possa essere sovrautilizzato ; certamente può Soprattutto pre- unique_ptr
, ci sono stati molti casi in cui ho appena usato un boost::shared_ptr
perché avevo bisogno di passare un puntatore RAII o di inserirlo in un elenco. Senza spostare la semantica e unique_ptr
, boost::shared_ptr
era l'unica soluzione reale.
E puoi usarlo in posti in cui non è necessario. Come detto sopra, la corretta struttura del codice può eliminare la necessità di alcuni usi di shared_ptr
. Ma se il tuo sistema non può essere strutturato come tale e continua a fare ciò di cui ha bisogno, shared_ptr
sarà di grande utilità.