Perché è sbagliato usare std :: auto_ptr con contenitori standard?

Perché è sbagliato usare std::auto_ptr con contenitori standard?

Lo standard C ++ dice che un elemento STL deve essere “copy-constructible” e “assignable”. In altre parole, un elemento deve poter essere assegnato o copiato e i due elementi sono logicamente indipendenti. std::auto_ptr non soddisfa questo requisito.

Prendi ad esempio questo codice:

 class X { }; std::vector > vecX; vecX.push_back(new X); std::auto_ptr pX = vecX[0]; // vecX[0] is assigned NULL. 

Per superare questa limitazione, dovresti usare i puntatori intelligenti std::unique_ptr , std::shared_ptr o std::weak_ptr o gli equivalenti boost se non hai C ++ 11. Ecco la documentazione della libreria boost per questi puntatori intelligenti.

La semantica della copia di auto_ptr non è compatibile con i contenitori.

In particolare, la copia di un auto_ptr su un altro non crea due oggetti uguali poiché uno ha perso la proprietà del puntatore.

Più in particolare, la copia di un auto_ptr fa sì che una delle copie lasci andare il puntatore. Quale di questi resti nel contenitore non è definito. Pertanto, è ansible perdere casualmente l’accesso ai puntatori se si memorizzano auto_ptrs nei contenitori.

Due articoli super eccellenti sull’argomento:

  • Puntatori intelligenti: cosa, perché, quali?
  • Guru della settimana # 25

I contenitori STL devono essere in grado di copiare gli elementi in essi archiviati e sono progettati in modo che l’originale e la copia siano equivalenti. oggetti puntatore automatico hanno un contratto completamente diverso, per cui la copia crea un trasferimento di proprietà. Ciò significa che i contenitori di auto_ptr mostreranno un comportamento strano, a seconda dell’utilizzo.

C’è una descrizione dettagliata di cosa può andare storto in Effective STL (Scott Meyers) item 8 e anche una descrizione non molto dettagliata in Effective C ++ (Scott Meyers) item 13.

I contenitori STL memorizzano copie di articoli contenuti. Quando viene copiato un auto_ptr, imposta il vecchio ptr su null. Molti metodi di contenitore sono interrotti da questo comportamento.

C ++ 03 Standard (ISO-IEC 14882-2003) come indicato al punto 3 della clausola 20.4.5:

[…] [ Nota: […] auto_ptr non soddisfa i requisiti CopyConstructible e Assignable per gli elementi del contenitore della libreria standard e pertanto l’istanziazione di un contenitore della libreria standard con un auto_ptr comporta un comportamento non definito. – nota finale ]

Lo standard C ++ 11 (ISO-IEC 14882-2011) dice nell’appendice D.10.1, paragrafo 3:

[…] Nota: […] Le istanze di auto_ptr soddisfano i requisiti di MoveConstructible e MoveAssignable, ma non soddisfano i requisiti di CopyConstructible e CopyAssignable. – nota finale]

Lo standard C ++ 14 (ISO-IEC 14882-2014) è riportato nell’appendice C.4.2 Allegato D: caratteristiche di compatibilità:

Modifica : i modelli di class auto_ptr, unary_function e binary_function, i template di funzione random_shuffle ei template di funzione (e i relativi tipi di ritorno) ptr_fun, mem_fun, mem_fun_ref, bind1st e bind2nd non sono definiti.
Motivazione : sostituito da nuove funzionalità.
Effetto sulla caratteristica originale : il codice valido C ++ 2014 che utilizza questi modelli di classi e modelli di funzioni potrebbe non riuscire a compilare in questo standard internazionale.