std :: auto_ptr in std :: unique_ptr


185

Con il nuovo standard in arrivo (e parti già disponibili in alcuni compilatori), il nuovo tipo std::unique_ptrdovrebbe essere un sostituto per std::auto_ptr.

Il loro utilizzo si sovrappone esattamente (quindi posso fare una ricerca / sostituzione globale sul mio codice (non che lo farei, ma se lo facessi)) o dovrei essere consapevole di alcune differenze che non sono evidenti dalla lettura della documentazione?

Anche se si tratta di un sostituto diretto, perché dargli un nuovo nome piuttosto che migliorarlo std::auto_ptr?

Risposte:


219

Non è possibile eseguire una ricerca / sostituzione globale perché è possibile copiarne una auto_ptr(con conseguenze note), ma è unique_ptrpossibile solo spostarla. Qualunque cosa assomigli

std::auto_ptr<int> p(new int);
std::auto_ptr<int> p2 = p; 

dovrà diventare almeno così

std::unique_ptr<int> p(new int);
std::unique_ptr<int> p2 = std::move(p);

Per quanto riguarda le altre differenze, unique_ptrpuò gestire correttamente le matrici (chiamerà delete[], mentre auto_ptrtenterà di chiamare delete.


101
d'altra parte, facendo questo trova / sostituisci comporterà solo errori di compilazione, non romperà silenziosamente il codice per quanto posso vedere. Quindi è sicuro farlo, se in seguito correggi manualmente gli errori di compilazione
jalf

7
@jalf: In effetti, non riesco a pensare a un contro-esempio che sarebbe ben definito con auto_ptrs e UB con unique_ptrs.
Cubbi,

1
quindi sembra che unique_ptr sia un miglioramento di auto_ptr: supporta array e rimuove ambiguità
Baiyan Huang

92

std::auto_ptre std::unique_ptrsono incompatibili in qualche modo e un calo nella sostituzione in altri. Quindi, nessuna ricerca / sostituzione non è abbastanza buona. Tuttavia, dopo aver trovato / sostituito il lavoro attraverso gli errori di compilazione dovrebbe risolvere tutto tranne i casi angolari strani. La maggior parte degli errori di compilazione richiederà l'aggiunta di a std::move.

  • Variabile dell'ambito della funzione:
    compatibile al 100%, a condizione che non venga passato per valore a un'altra funzione.
  • Tipo di valore restituito:
    non compatibile al 100% ma compatibile al 99% non sembra sbagliato.
  • Parametro di funzione in base al valore:
    100% compatibile con un avvertimento, unique_ptri messaggi di posta elettronica devono essere passati attraverso una std::movechiamata. Questo è semplice in quanto il compilatore si lamenterà se non lo capisci bene.
  • Parametro funzione per riferimento:
    compatibile al 100%.
  • Variabile membro della classe:
    questa è complicata. std::auto_ptrLa semantica delle copie è malvagia. Se la classe non consente la copia, la std::unique_ptrsostituzione viene interrotta. Tuttavia, se hai provato a fornire alla classe una semantica della copia ragionevole, dovrai modificare il std::auto_ptrcodice di gestione. Questo è semplice in quanto il compilatore si lamenterà se non lo capisci bene. Se hai permesso di copiare una classe con un std::auto_ptrmembro senza alcun codice speciale, allora vergogna e buona fortuna.

In sintesi, std::unique_ptrè un ininterrotto std::auto_ptr. Non consente in fase di compilazione comportamenti che spesso erano errori quando si utilizza a std::auto_ptr. Quindi, se hai usato std::auto_ptrcon le cure necessarie, passare a std::unique_ptrdovrebbe essere semplice. Se hai fatto affidamento sul std::auto_ptrcomportamento strano, devi comunque riformattare il codice.


8
+1 per "devi comunque riformattare il tuo codice". auto_ptrs è buono solo per ciò che 20.4.5 / 3 dice che è buono.
Cubbi,

8
Consentitemi di aggiungere che è necessario sostituire auto_ptr con unique_ptr nel codice e correggere gli errori di compilazione. Saresti sorpreso di quanti bug scoprirai.
Bartosz Milewski,

36

AFAIK, unique_ptrnon è un sostituto diretto. Il principale difetto che corregge è il trasferimento implicito della proprietà.

std::auto_ptr<int> a(new int(10)), b;
b = a; //implicitly transfers ownership

std::unique_ptr<int> a(new int(10)), b;
b = std::move(a); //ownership must be transferred explicitly

D'altra parte, unique_ptravranno funzionalità completamente nuove: possono essere archiviate in contenitori.


8
Scott Meyers ha anche menzionato nel suo "Effective C ++" (3rd Edition) Item 13 (page 64) che i contenitori STL richiedono che il loro contenuto mostri un comportamento di copia "normale", quindi i container di auto_ptrnon sono ammessi.
Qiang Xu,

31

Herb Sutter ha una bella spiegazione su GotW # 89 :

Qual è il problema con auto_ptr? auto_ptr è caritativamente caratterizzato come un coraggioso tentativo di creare un unique_ptr prima che C ++ avesse spostato la semantica. auto_ptr è ora obsoleto e non deve essere utilizzato nel nuovo codice.

Se hai auto_ptr in una base di codice esistente, quando ne hai la possibilità prova a fare una ricerca globale e sostituire auto_ptr in unique_ptr; la stragrande maggioranza degli usi funzionerà allo stesso modo e potrebbe esporre (come errore di compilazione) o correggere (silenziosamente) un paio di bug che non sapevi di avere.

In altre parole, mentre una ricerca e sostituzione globale può "rompere" temporaneamente il codice, dovresti comunque farlo: potrebbe richiedere del tempo per correggere gli errori di compilazione, ma ti farà risparmiare molti più problemi a lungo termine.


Ottimo collegamento Molte grazie!
fotNelton,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.