c++ - smart - Ventajas de usar std:: make_unique sobre el nuevo operador
shared_ptr (2)
Ventajas
-
make_unique
enseña a los usuarios "nunca digasnew
/delete
ynew[]
/delete[]
" sin renuncias. -
make_unique
comparte dos ventajas conmake_shared
(excluyendo la tercera ventaja, mayor eficiencia). Primero,unique_ptr<LongTypeName> up(new LongTypeName(args))
debe mencionarLongTypeName
dos veces, mientras queauto up = make_unique<LongTypeName>(args)
menciona una vez. -
make_unique
evita la pérdida de orden de evaluación no especificada desencadenada por expresiones comofoo(unique_ptr<X>(new X)
,unique_ptr<Y>(new Y))
. (Seguir el consejo "nunca digasnew
" es más simple que "nunca digasnew
, a menos que lo des inmediatamente a ununique_ptr
"). -
make_unique
se implementa cuidadosamente para garantizar la seguridad de las excepciones y se recomienda antes de llamar directamente a los constructoresunique_ptr
.
Cuando no use
make_unique
-
No use
make_unique
si necesita un eliminador personalizado o si está adoptando un puntero sin formato desde otro lugar.
Fuentes
Esta pregunta ya tiene una respuesta aquí:
¿Cuáles son las ventajas de usar
std::make_unique
sobre el
new
operador para inicializar
std::unique_ptr
?
En otras palabras, ¿por qué es
std::unique_ptr<SomeObject> a = std::make_unique(SomeObject(...))
mejor que hacerlo
std::unique_ptr<SomeObject> a = new SomeObject(...)
Intenté buscar mucho en línea y sé que es una buena regla general evitar al operador
new
en C ++ moderno, pero no estoy seguro de cuáles son las ventajas en este escenario exacto.
¿Previene cualquier tipo de pérdida de memoria que pueda ocurrir?
¿Es más rápido hacer un
std::make_unique
que usar
new
?
La diferencia es que
std::make_unique
devuelve un objeto de tipo
std::unique_ptr
y
new
devuelve un puntero al objeto creado.
Para fallas de asignación de memoria, ambos arrojarán.
Espera, no es tan simple.
Leer más
Considere tal función a continuación:
void func(ClassA* a, ClassB* b){
......
}
Cuando realiza una llamada como
func(new A(), new B())
;
El compilador puede elegir evaluar los argumentos de la función de izquierda a derecha, o en el orden que lo desee.
Asumamos una evaluación de izquierda a derecha: ¿Qué sucede cuando la primera expresión
new
tiene éxito pero la segunda expresión
new
arroja?
El verdadero peligro aquí es cuando atrapas esa excepción;
Sí, puede haber detectado la excepción lanzada por el
new B()
y reanudar la ejecución normal, pero el
new A()
ya tuvo éxito y su memoria se filtrará en silencio.
Nadie para limpiarlo ... *
sollozos
...
Pero con
make_unique
, no puede haber una fuga porque sucederá el desenrollado de la pila (y se ejecutará el destructor del objeto creado anteriormente).
Por lo tanto, tener preferencia por
make_unique
lo
make_unique
a la
seguridad de excepción
.
En este caso,
std::make_unique
proporciona una
"
Seguridad de excepción básica
" de
que la memoria asignada y el objeto creado por
new
nunca quedarán huérfanos
std::make_unique
.
Incluso hasta el final de los tiempos ... :-)
Deberías leer Herb Sutter GoTW102