std :: auto_ptr a std :: unique_ptr

185

Con la llegada del nuevo estándar (y partes ya disponibles en algunos compiladores), std::unique_ptrse supone que el nuevo tipo es un reemplazo std::auto_ptr.

¿Su uso se superpone exactamente (por lo que puedo hacer una búsqueda / reemplazo global en mi código (no es que lo haría, pero si lo hiciera)) o debería estar al tanto de algunas diferencias que no son evidentes al leer la documentación?

Además, si es un reemplazo directo, ¿por qué darle un nuevo nombre en lugar de solo mejorarlo std::auto_ptr?

Martin York
fuente

Respuestas:

219

No puede hacer una búsqueda / reemplazo global porque puede copiar un auto_ptr(con consecuencias conocidas), pero unique_ptrsolo se puede mover. Cualquier cosa que se parezca

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

tendrá que ser al menos así

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

En cuanto a otras diferencias, unique_ptrpuede manejar matrices correctamente (llamará delete[], mientras auto_ptrque intentará llamar delete.

Cubbi
fuente
101
Por otro lado, hacer esto buscar / reemplazar solo generará errores de compilación, no romperá el código en silencio hasta donde puedo ver. Por lo tanto, es seguro hacerlo, si luego corrige manualmente los errores de compilación
jalf
77
@jalf: De hecho, no puedo pensar en un contraejemplo que estaría bien definido con auto_ptrs y UB con unique_ptrs.
Cubbi
1
así que parece que unique_ptr es una mejora de auto_ptr: admite la matriz y elimina la ambigüedad
Baiyan Huang
92

std::auto_ptry std::unique_ptrson incompatibles en algunos aspectos y una caída en el reemplazo en otros. Por lo tanto, no buscar / reemplazar no es lo suficientemente bueno. Sin embargo, después de buscar / reemplazar el trabajo a través de los errores de compilación, debería solucionar todo, excepto los casos extraños de esquina. La mayoría de los errores de compilación requerirán agregar a std::move.

  • Variable del alcance de la función:
    100% compatible, siempre que no lo pase por valor a otra función.
  • Tipo de retorno:
    no es 100% compatible, pero 99% compatible no parece incorrecto.
  • Parámetro de función por valor:
    100% compatible con una advertencia, unique_ptrs debe pasar a través de una std::movellamada. Este es simple ya que el compilador se quejará si no lo hace bien.
  • Parámetro de función por referencia:
    100% compatible.
  • Variable miembro de clase:
    esta es complicada. std::auto_ptrLas semánticas de copia son malvadas. Si la clase no permite copiar, entonces std::unique_ptrhay una caída en el reemplazo. Sin embargo, si trató de darle a la clase una semántica de copia razonable, deberá cambiar el std::auto_ptrcódigo de manejo. Esto es simple ya que el compilador se quejará si no lo hace bien. Si permitiste copiar una clase con un std::auto_ptrmiembro sin ningún código especial, entonces, qué vergüenza y buena suerte.

En resumen, std::unique_ptres un ininterrumpido std::auto_ptr. No permite en tiempo de compilación comportamientos que a menudo eran errores al usar a std::auto_ptr. Entonces, si lo usó std::auto_ptrcon el cuidado que necesitaba, cambiar a std::unique_ptrdebería ser simple. Si confió en std::auto_ptrel comportamiento extraño, entonces necesita refactorizar su código de todos modos.

código_deft
fuente
8
+1 para "necesita refactorizar su código de todos modos". auto_ptrs solo son buenos para lo que 20.4.5 / 3 dice que son buenos.
Cubbi
8
Permítanme agregar a esto que, por supuesto, debería reemplazar auto_ptr por unique_ptr en su código y corregir los errores de compilación. Te sorprendería cuántos errores descubrirá esto.
Bartosz Milewski
36

AFAIK, unique_ptrno es un reemplazo directo. El principal defecto que corrige es la transferencia implícita de propiedad.

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

Por otro lado, unique_ptrtendrá capacidades completamente nuevas: se pueden almacenar en contenedores.

TíoBens
fuente
8
Scott Meyers también mencionó en su artículo 13 "Eficaz C ++" (3ª edición) (página 64) que los contenedores STL requieren que sus contenidos exhiban un comportamiento de copia "normal", por lo que auto_ptrno se permiten contenedores de .
Qiang Xu
31

Herb Sutter tiene una buena explicación sobre GotW # 89 :

¿Cuál es el trato con auto_ptr? auto_ptr se caracteriza más caritativamente como un valiente intento de crear un unique_ptr antes de que C ++ tuviera semántica de movimiento. auto_ptr ahora está en desuso y no debe usarse en código nuevo.

Si tiene auto_ptr en una base de código existente, cuando tenga la oportunidad intente realizar una búsqueda y reemplazo global de auto_ptr a unique_ptr; la gran mayoría de los usos funcionarán de la misma manera, y podría exponer (como un error en tiempo de compilación) o corregir (silenciosamente) un error o dos que no sabía que tenía.

En otras palabras, si bien una búsqueda y reemplazo global puede "romper" su código temporalmente, debe hacerlo de todos modos: puede tomar algún tiempo corregir los errores de compilación, pero a la larga le ahorrará muchos más problemas.

ValarDohaeris
fuente
Gran enlace ¡Muchas gracias!
fotNelton