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

make_shared - ¿Cuál es la diferencia entre un std:: shared_ptr vacío y uno nulo en C++?



example c++11 (2)

La página cplusplus.com shared_ptr establece una distinción entre un std::shared_ptr vacío y un shared_ptr nulo . La página cppreference.com no menciona explícitamente la distinción, pero usa tanto "vacío" como comparación con nullptr en su descripción del comportamiento std::shared_ptr .

¿Hay alguna diferencia entre un shared_ptr vacío y uno nulo? ¿Hay algún caso de uso para estos punteros de comportamiento mixto? ¿Tiene sentido un nulo no vacío shared_ptr ? ¿Habría algún caso en el uso normal (es decir, si no construyó uno explícitamente) en el que podría terminar con un shared_ptr vacío pero no nulo?

¿Alguna de estas respuestas cambia si está utilizando la versión Boost en lugar de la versión C ++ 11?


Es un rincón extraño del comportamiento shared_ptr . Tiene un constructor que le permite hacer un shared_ptr que posee algo y apunta a otra cosa:

template< class Y > shared_ptr( const shared_ptr<Y>& r, T *ptr );

shared_ptr construido con este constructor comparte la propiedad con r , pero apunta a lo que ptr apunta (es decir, llamar a get() u operator->() devolverá ptr ). Esto es útil para los casos en que ptr apunta a un subobjeto (por ejemplo, un miembro de datos) del objeto propiedad de r .

La página que vinculó llama un shared_ptr que no posee nada vacío , y shared_ptr que apunta a nada (es decir, cuyo get() == nullptr ) es nulo . ( Vacío se usa en este sentido por el estándar; nulo no lo es.) Puede construir un shared_ptr nulo pero no vacío, pero no será muy útil. Un shared_ptr vacío pero no nulo es esencialmente un puntero no propietario, que se puede usar para hacer algunas cosas extrañas como pasar un puntero a algo asignado en la pila a una función que espera un shared_ptr (pero sugeriría golpear a quien sea Poner shared_ptr dentro de la API primero).

boost::shared_ptr también tiene este constructor , al que llaman constructor de alias .


¿Hay alguna diferencia entre un shared_ptr vacío y uno nulo?

shared_ptr vacío no tiene bloque de control y su recuento de uso se considera 0. La copia de shared_ptr vacío es otro shared_ptr vacío. Ambos son shared_ptr s separados que no comparten un bloque de control común porque no lo tienen. shared_ptr vacío se puede construir con el constructor predeterminado o con el constructor que toma nullptr .

shared_ptr no vacío shared_ptr tiene bloque de control que se puede compartir con otros shared_ptr s. La copia de null no vacío shared_ptr es shared_ptr que comparte el mismo bloque de control que el shared_ptr original, shared_ptr lo que el recuento de uso no es 0. Se puede decir que todas las copias de shared_ptr comparten el mismo nullptr . shared_ptr no shared_ptr se puede construir con un puntero nulo del tipo de objeto (no nullptr )

Aquí hay un ejemplo:

#include <iostream> #include <memory> int main() { std::cout << "std::shared_ptr<int> ptr1:" << std::endl; { std::shared_ptr<int> ptr1; std::cout << "/tuse count before copying ptr: " << ptr1.use_count() << std::endl; std::shared_ptr<int> ptr2 = ptr1; std::cout << "/tuse count after copying ptr: " << ptr1.use_count() << std::endl; std::cout << "/tptr1 is " << (ptr1 ? "not null" : "null") << std::endl; } std::cout << std::endl; std::cout << "std::shared_ptr<int> ptr1(nullptr):" << std::endl; { std::shared_ptr<int> ptr1(nullptr); std::cout << "/tuse count before copying ptr: " << ptr1.use_count() << std::endl; std::shared_ptr<int> ptr2 = ptr1; std::cout << "/tuse count after copying ptr: " << ptr1.use_count() << std::endl; std::cout << "/tptr1 is " << (ptr1 ? "not null" : "null") << std::endl; } std::cout << std::endl; std::cout << "std::shared_ptr<int> ptr1(static_cast<int*>(nullptr))" << std::endl; { std::shared_ptr<int> ptr1(static_cast<int*>(nullptr)); std::cout << "/tuse count before copying ptr: " << ptr1.use_count() << std::endl; std::shared_ptr<int> ptr2 = ptr1; std::cout << "/tuse count after copying ptr: " << ptr1.use_count() << std::endl; std::cout << "/tptr1 is " << (ptr1 ? "not null" : "null") << std::endl; } std::cout << std::endl; return 0; }

Produce:

std::shared_ptr<int> ptr1: use count before copying ptr: 0 use count after copying ptr: 0 ptr1 is null std::shared_ptr<int> ptr1(nullptr): use count before copying ptr: 0 use count after copying ptr: 0 ptr1 is null std::shared_ptr<int> ptr1(static_cast<int*>(nullptr)) use count before copying ptr: 1 use count after copying ptr: 2 ptr1 is null

http://coliru.stacked-crooked.com/a/54f59730905ed2ff