shared_ptr example c++ c++11 shared-ptr make-shared

c++ - shared_ptr example



¿Std:: make_shared() usa asignadores personalizados? (2)

Considere este código :

#include <memory> #include <iostream> class SomeClass { public: SomeClass() { std::cout << "SomeClass()" << std::endl; } ~SomeClass() { std::cout << "~SomeClass()" << std::endl; } void* operator new(std::size_t size) { std::cout << "Custom new" << std::endl; return ::operator new(size); } void operator delete(void* ptr, std::size_t size) { std::cout << "Custom delete" << std::endl; ::operator delete(ptr); } }; int main() { std::shared_ptr<SomeClass> ptr1(new SomeClass); std::cout << std::endl << "Another one..." << std::endl << std::endl; std::shared_ptr<SomeClass> ptr2(std::make_shared<SomeClass>()); std::cout << std::endl << "Done!" << std::endl << std::endl; }

Aquí está su salida:

Custom new SomeClass() Another one... SomeClass() Done! ~SomeClass() ~SomeClass() Custom delete

Claramente, std::make_shared() no llamó al new operador, está usando un asignador personalizado. ¿Es este el comportamiento estándar para std::make_shared() ?


Para expandir la respuesta correcta de Mat, make_shared se implementa típicamente asignando un objeto que contiene los shared_ptr referencia shared_ptr y un búfer de bytes sin inicializar:

template<typename T> struct shared_count_inplace { long m_count; long weak_count; typename std::aligned_storage<sizeof(T)>::type m_storage; // ... };

Este es el tipo que se asignará en el montón, no su tipo, por lo que no se llama al new tipo. Luego, su tipo se construirá usando una ubicación new en la ubicación (void*)&m_storage .


Sí, este es el comportamiento estándar. Desde el estándar (§20.7.2.2.6 shared_ptr creation ):

Efectos: Asigna memoria adecuada para un objeto de tipo T y construye un objeto en esa memoria a través de la nueva expresión de ubicación ::new (pv) T(std::forward<Args>(args)...).

Esto permite que make_shared asigne el almacenamiento tanto para el objeto como para la estructura de datos para el propio puntero compartido (el "bloque de control") en una sola asignación, por razones de eficiencia.

Podría usar std::allocate_shared si desea controlar esa asignación de almacenamiento.