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à.