Perché auto_ptr è deprecato?

Ho sentito che auto_ptr è stato deprecato in C ++ 11. Qual è la ragione di questo?

Inoltre vorrei sapere la differenza tra auto_ptr e shared_ptr .

La sostituzione diretta di auto_ptr (o comunque la cosa più vicina ad una) è unique_ptr . Per quanto riguarda il “problema”, è piuttosto semplice: auto_ptr trasferisce la proprietà quando viene assegnata. unique_ptr trasferisce anche la proprietà, ma grazie alla codifica della semantica del movimento e alla magia dei riferimenti rvalue, può farlo in modo considerevolmente più naturale. Inoltre “si adatta” al resto della libreria standard in modo considerevolmente migliore (anche se, in tutta onestà, parte di ciò è dovuto al fatto che il resto della libreria cambia per adattarsi alla semantica del movimento invece di richiedere sempre la copia).

Anche il cambio di nome è (IMO) un benvenuto – auto_ptr non ti dice molto su cosa tenta di automatizzare, mentre unique_ptr è una descrizione abbastanza ragionevole (se concisa) di ciò che viene fornito.

Ho trovato le risposte esistenti grandiose, ma dal punto di vista dei puntatori. IMO, una risposta ideale dovrebbe avere la risposta prospettica dell’utente / programmatore.

Per prima cosa (come indicato da Jerry Coffin nella sua risposta)

  • auto_ptr potrebbe essere sostituito da shared_ptr o unique_ptr a seconda della situazione

shared_ptr: se si è preoccupati di liberare risorse / memoria e se si dispone di più di una funzione che potrebbe utilizzare le volte AT-DIFFERENT dell’object, andare con shared_ptr.

Da DIFFERENT-Times, pensate a una situazione in cui l’object-ptr è memorizzato in più strutture dati e successivamente acceduto. Più thread, ovviamente, è un altro esempio.

unique_ptr: Se tutto ciò che ti interessa è liberare memoria, e l’accesso all’object è SEQUENTIAL, quindi vai a unique_ptr.

Per SEQUENTIAL, intendo, in qualsiasi punto l’accesso sarà accessibile da un contesto. Ad esempio un object che è stato creato e utilizzato subito dopo la creazione dal creatore. Dopo la creazione, l’object è memorizzato nella FIRST data-structure. Quindi l’object viene distrutto dopo la struttura dei dati ONE o spostato in SECONDO struttura dei dati.

Da questa linea, farò riferimento a shared / unique _ptr come puntatori intelligenti. (auto_ptr è anche smart-pointer BUT a causa di difetti nel suo design, per il quale sono deprecati, e che penso indicherò nelle righe successive, non dovrebbero essere raggruppati con smart-pointer.)

La ragione più importante del motivo per cui auto_ptr è stato deprecato in favore di smart-pointer è la semantica degli assegnamenti Se non fosse per quella ragione, avrebbero aggiunto tutti i nuovi extra della semantica del movimento a auto_ptr invece di deprecarlo. Dato che la semantica del compito era la caratteristica più sgradita, volevano che quella funzione andasse via, ma dal momento che c’è del codice scritto che usa quella semantica, (che il comitato degli standard non può cambiare), hanno dovuto lasciare andare auto_ptr, invece di modificandolo.

Dal link: http://www.cplusplus.com/reference/memory/unique_ptr/operator=/

Tipo di incarichi supportati da unqiue_ptr

  • move incarico (1)
  • assegna un puntatore nullo (2)
  • type-cast assignment (3)
  • copia incarico (cancellato!) (4)

Da: http://www.cplusplus.com/reference/memory/auto_ptr/operator=/

Tipo di incarichi supportati da auto_ptr

  • copia incarico (4) colpevole

Ora venendo alla ragione PERCHÉ l’assegnazione della copia stessa era così antipatica, ho questa teoria:

  1. Non tutti i programmatori leggono libri o standard
  2. auto_ptr sul lato di esso, promette la proprietà dell’object
  3. la clausola little- * (pun intended), auto_ptr, che non è letta da tutti i programmatori, consente, l’assegnazione di un auto_ptr a un altro, e trasferisce la proprietà.
  4. La ricerca ha dimostrato che questo comportamento è destinato al 3,1415926535% di tutti gli usi e non è previsto in altri casi.

Il comportamento non intenzionale è davvero sgradito e quindi l’antipatia per l’auto_ptr.

(Per il 3.1415926536% di programmatori che intenzionalmente vogliono trasferire la proprietà C ++ 11 ha dato loro std :: move (), che ha reso chiara la loro intenzione per tutti gli stagisti che leggeranno e manterranno il codice.)

shared_ptr può essere memorizzato all’interno di contenitori. auto_ptr non può.

BTW unique_ptr è in realtà la sostituzione automatica auto_ptr , combina le migliori caratteristiche di std::auto_ptr e boost::scoped_ptr .

Un altro tentativo di spiegare la differenza ….

Funzionalmente, std::unique_ptr C ++ 11 è il “fisso” std::auto_ptr : entrambi sono adatti quando – in qualsiasi momento durante l’esecuzione – ci dovrebbe essere un singolo proprietario di puntatore intelligente per un object puntato .

La differenza cruciale è nella costruzione della copia o nell’assegnazione da un altro puntatore intelligente senza scadenza, mostrato nelle righe => seguenti:

  std::auto_ptr ap(...); std::auto_ptr ap2(get_ap_to_T()); // take expiring ownership => std::auto_ptr ap3(ap); // take un-expiring ownership ala ap3(ap.release()); ap->xyz; // oops... can still try to use ap, expecting it to be non-NULL std::unique_ptr up(...); std::unique_ptr up2(get_up_to_T()); // take expiring ownership => std::unique_ptr up3(up); // COMPILE ERROR: can't take un-expiring ownership => std::unique_ptr up4(std::move(up)); // EXPLICIT code allowed => std::unique_ptr up4(up.release()); // EXPLICIT code allowed 

Sopra, ap3 tranquillamente “ruba” la proprietà di *ap , lasciando ap impostato su nullptr , e il problema è che può accadere troppo facilmente, senza che il programmatore abbia pensato attraverso la sua sicurezza.

Ad esempio, se una class / struct ha un membro std::auto_ptr , quindi fare una copia di un’istanza release il puntatore dall’istanza che si sta copiando: quella strana e pericolosamente confusa semantica come di solito la copia di qualcosa non la modifica. È facile per l’autore della class / struct trascurare il rilascio del puntatore quando ragiona su invarianti e stato, e conseguentemente accidentalmente tenta di dereferenziare smart-pointer mentre è nullo, o semplicemente non ha ancora l’accesso / la proprietà previsti dei dati puntati.

auto_ptr non può essere utilizzato nei contenitori STL perché ha un costruttore di copia che non soddisfa i requisiti del contenitore CopyConstructible . unique_ptr non implementa un costruttore di copie, quindi i contenitori utilizzano metodi alternativi. unique_ptr può essere utilizzato in contenitori ed è più veloce per gli algoritmi standard rispetto a shared_ptr.

 #include  #include  #include  #include  using namespace std; int main() { cout << boolalpha; cout << "is_copy_constructible:" << endl; cout << "auto_ptr: " << is_copy_constructible< auto_ptr >::value << endl; cout << "unique_ptr: " << is_copy_constructible< unique_ptr >::value << endl; cout << "shared_ptr: " << is_copy_constructible< shared_ptr >::value << endl; vector i_v; i_v.push_back(1); cout << "i_v=" << i_v[0] << endl; vector i_v2=i_v; cout << "i_v2=" << i_v2[0] << endl; vector< unique_ptr > u_v; u_v.push_back(unique_ptr(new int(2))); cout << "u_v=" << *u_v[0] << endl; //vector< unique_ptr > u_v2=u_v; //will not compile, need is_copy_constructible == true vector< unique_ptr > u_v2 =std::move(u_v); // but can be moved cout << "u_v2=" << *u_v2[0] << " length u_v: " < > s_v; shared_ptr s(new int(3)); s_v.push_back(s); cout << "s_v=" << *s_v[0] << endl; vector< shared_ptr > s_v2=s_v; cout << "s_v2=" << *s_v2[0] << endl; vector< auto_ptr > a_v; //USAGE ERROR return 0; } >cxx test1.cpp -o test1 test1.cpp: In function âint main()â: test1.cpp:33:11: warning: âauto_ptrâ is deprecated (declared at /apps/hermes/sw/gcc/gcc-4.8.5/include/c++/4.8.5/backward/auto_ptr.h:87) [-Wdeprecated-declarations] vector< auto_ptr > a_v; //USAGE ERROR ^ >./test1 is_copy_constructible: auto_ptr: false unique_ptr: false shared_ptr: true i_v=1 i_v2=1 u_v=2 s_v=3 s_v2=3