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