c++ - shared_ptr - std:: auto_ptr a std:: unique_ptr
smart pointers c++ (4)
Con la llegada del nuevo estándar (y las partes ya están disponibles en algunos compiladores), se supone que el nuevo tipo std::unique_ptr
es un reemplazo para std::auto_ptr
.
¿Su uso se superpone exactamente (por lo que puedo hacer un descubrimiento / reemplazo global en mi código (no es que lo haga, pero si lo hiciera)) o debería ser consciente de algunas diferencias que no son evidentes al leer la documentación?
También si es un reemplazo directo (por qué darle un nuevo nombre) en lugar de simplemente mejorar el std::auto_ptr
.
AFAIK, unique_ptr
no 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_ptr
tendrá capacidades completamente nuevas: se pueden almacenar en contenedores.
Herb Sutter tiene una buena explicación sobre GotW # 89 :
¿Cuál es el problema con auto_ptr? auto_ptr se caracteriza más caritativamente como un valiente intento de crear un unique_ptr antes de que C ++ tenga una semántica de movimiento. auto_ptr ahora está en desuso, y no debería usarse en un 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á de la misma manera, y podría exponer (como un error de tiempo de compilación) o arreglar (silenciosamente) un error o dos que no sabías que tenías.
En otras palabras, aunque una búsqueda y reemplazo global puede "romper" temporalmente su código, debe hacerlo de todos modos: puede tomar algún tiempo corregir los errores de compilación, pero le ahorrará muchos más problemas a largo plazo.
No puede hacer un descubrimiento / reemplazo global porque puede copiar un auto_ptr
(con consecuencias conocidas), pero un unique_ptr
solo se puede mover. Cualquier cosa que se vea
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_ptr
puede manejar matrices correctamente (llamará a delete[]
, mientras que auto_ptr
intentará llamar a delete
.
std::auto_ptr
y std::unique_ptr
son incompatibles de alguna manera y un reemplazo en otros. Entonces, no encontrar / reemplazar no es lo suficientemente bueno. Sin embargo, después de encontrar / reemplazar el trabajo a través de los errores de compilación debería arreglar todo, excepto casos de esquina extraños. La mayoría de los errores de compilación requerirán agregar un std::move
.
- Variable de alcance de función:
100% compatible, siempre que no lo transfiera por valor a otra función. - Tipo de devolución:
no es 100% compatible, pero 99% compatible no parece estar mal. - Parámetro de función por valor:
100% compatible con una advertencia,unique_ptr
s se debe pasar a través de una llamadastd::move
. 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 la clase:
Este es complicado.std::auto_ptr
s la semántica de copia es malvada. Si la clase no permite la copia,std::unique_ptr
es un reemplazo. Sin embargo, si intentas darle a la clase una semántica de copia razonable, deberás cambiar el código de manejostd::auto_ptr
. Esto es simple ya que el compilador se quejará si no lo hace bien. Si permitiste copiar una clase con un miembrostd::auto_ptr
sin ningún código especial, entonces la culpa es de ti y buena suerte.
En resumen, std::unique_ptr
es un std::auto_ptr
ininterrumpido. No permite comportamientos de tiempo de compilación que a menudo son errores al usar std::auto_ptr
. Por lo tanto, si utilizó std::auto_ptr
con el cuidado que necesitaba, cambiar a std::unique_ptr
debería ser simple. Si std::auto_ptr
el comportamiento impar de std::auto_ptr
, entonces necesitas refactorizar tu código de todos modos.