c++ - smart - shared_ptr
¿Por qué usar std:: make_unique en C++ 17? (4)
Cada uso de lo
new
tiene que ser auditado con mayor cuidado para asegurar la corrección de por vida;
¿Se borra?
¿Sólo una vez?
Todo uso de
make_unique
no para esas características adicionales;
siempre que el objeto propietario tenga una vida "correcta", recursivamente hace que el puntero único tenga "correcta".
Ahora, es cierto que
unique_ptr<Foo>(new Foo())
es idéntico en todos los aspectos
1
a
make_unique<Foo>()
;
solo requiere un "grep su código fuente más simple para todos los usos de los
new
para auditarlos".
En
realidad soy una mentira en el caso general.
El reenvío perfecto no es perfecto,
{}
, init predeterminado, las matrices son excepciones.
Según tengo entendido, C ++ 14 introdujo
std::make_unique
porque, debido a que no se especificó el orden de evaluación de parámetros, esto no era seguro:
f(std::unique_ptr<MyClass>(new MyClass(param)), g()); // Syntax A
(Explicación: si la evaluación asigna primero la memoria para el puntero en bruto, entonces se llama
g()
y se lanza una excepción antes de la construcción
std::unique_ptr
, entonces la memoria se filtra).
Llamar a
std::make_unique
era una forma de restringir el orden de las llamadas y así hacer las cosas más seguras:
f(std::make_unique<MyClass>(param), g()); // Syntax B
Desde entonces, C ++ 17 ha aclarado el orden de evaluación, haciendo que la Sintaxis A sea segura también, así que aquí está mi pregunta:
¿hay alguna razón para usar
std::make_unique
sobre el
std::make_unique
std::unique_ptr
en C ++ 17?
¿Puedes dar algunos ejemplos?
A partir de ahora, la única razón que puedo imaginar es que permite escribir
MyClass
solo una vez (asumiendo que no es necesario confiar en el polimorfismo con
std::unique_ptr<Base>(new Derived(param))
).
Sin embargo, eso parece ser una razón bastante débil, especialmente cuando
std::make_unique
no permite especificar un borrado mientras que el constructor de
std::unique_ptr
hace.
Y para ser claro, no estoy abogando por eliminar
std::make_unique
de la Biblioteca estándar (mantenerlo tiene sentido, al menos para la compatibilidad con versiones anteriores), sino preguntarme si todavía hay situaciones en las que es altamente preferible
std::unique_ptr
La razón es tener código más corto sin duplicados. Comparar
f(std::unique_ptr<MyClass>(new MyClass(param)), g());
f(std::make_unique<MyClass>(param), g());
MyClass
,
new
y tirantes.
Solo cuesta un personaje más en comparación con
ptr
.
Tienes razón en que la razón principal fue eliminada.
Todavía existen las pautas para
no usar nuevas
y que son menos razones para escribir (no es necesario repetir el tipo o usar la palabra
new
).
Es cierto que esos no son argumentos sólidos, pero realmente me gusta no ver los
new
en mi código.
Además, no te olvides de la consistencia.
Absolutamente debe usar
make_shared
por lo que usar
make_unique
es natural y se ajusta al patrón.
Entonces es trivial cambiar
std::make_unique<MyClass>(param)
a
std::make_shared<MyClass>(param)
(o la inversa) donde la sintaxis A requiere mucho más de una reescritura.
make_unique
distingue
T
de
T[]
y
T[N]
,
unique_ptr(new ...)
no lo hace.
Puede obtener fácilmente un comportamiento indefinido al pasar un puntero que era
new[]
ed a
unique_ptr<T>
, o al pasar un puntero que fue
new
a una
unique_ptr<T[]>
.