c++ - smart - std:: initialización shared_ptr: make_shared<Foo>() vs shared_ptr<T>(nuevo Foo)
smart pointers c++ (3)
Ambos ejemplos son bastante más detallados de lo necesario:
std::shared_ptr<int> p(new int); // or ''=shared_ptr<int>(new int)'' if you insist
auto p = std::make_shared<int>(); // or ''std::shared_ptr<int> p'' if you insist
¿Cual es la diferencia?
La principal diferencia es que la primera requiere dos asignaciones de memoria: una para el objeto gestionado ( new int
) y otra para el recuento de referencias. make_shared
debe asignar un solo bloque de memoria y crear ambos en eso.
¿Cuál debería preferir y por qué?
Por lo general, debes usar make_shared
ya que es más eficiente. Como se señala en otra respuesta, también evita cualquier posibilidad de pérdida de memoria, ya que nunca tiene un puntero sin formato al objeto administrado.
Sin embargo, como se señala en los comentarios, tiene la desventaja potencial de que la memoria no se liberará cuando se destruya el objeto, si todavía hay punteros débiles que impiden que se borre el recuento compartido.
Esta pregunta ya tiene una respuesta aquí:
Cuál es la diferencia entre:
std::shared_ptr<int> p = std::shared_ptr<int>( new int );
y
std::shared_ptr<int> p = std::make_shared< int >();
?
¿Cuál debería preferir y por qué?
PD: Bastante seguro de que esto ya debe haber sido respondido, pero no puedo encontrar una pregunta similar.
Por el contrario, la declaración std::shared_ptr<T> p(new T(Args...))
realiza al menos dos asignaciones de memoria, lo que puede generar una sobrecarga innecesaria.
Además, f(shared_ptr<int>(new int(42)), g())
puede provocar pérdida de memoria si g arroja una excepción. Este problema no existe si se usa make_shared.
Así que recomendaría el método make_shared
si es posible.
Tenga en cuenta que make_shared
limita a utilizar las funciones predeterminadas de asignación / desasignación, por lo que si desea tener más control, make_shared
no es una opción. En otras palabras, algo como
std::shared_ptr<uint8_t>(p, [](uint8_t *p){ /*user code */});
es imposible usando make_shared
. Uno podría usar allocate_shared
lugar, pero solo se puede especificar el asignador, no un eliminador. Algunas veces es necesario controlar la asignación y eliminación de la clase envuelta.