unique_ptr - smart pointers c++ 11




¿Por qué usar std:: make_unique en C++ 17? (3)

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


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.


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 .


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[]> .





unique-ptr