c++ - ¿Cómo shared_ptr<void> sabe qué destructor usar?
shared-ptr (2)
El estado compartido en copropiedad de los punteros compartidos también contiene un eliminador, una función como el objeto que se alimenta al objeto administrado al final de su vida útil para liberarlo. Incluso podemos especificar nuestro propio eliminador utilizando el constructor apropiado . La forma en que se almacena el eliminador, así como cualquier tipo de borrado que sufra es un detalle de implementación. Pero basta con decir que el estado compartido contiene una función que sabe exactamente cómo liberar el recurso de propiedad.
Ahora, cuando creamos un objeto de un tipo concreto con
make_shared<Thing>()
y no proporcionamos un borrador, el estado compartido está configurado para contener algún borrador predeterminado que puede liberar una
Thing
.
La implementación puede generar uno solo desde el argumento de la plantilla.
Y dado que está almacenado como parte del estado compartido, no depende del tipo
T
de cualquier
shared_pointer<T>
que pueda estar compartiendo la propiedad del estado.
Siempre sabrá cómo liberar la
Thing
.
Entonces, incluso cuando hacemos de
voidPtr
el único puntero restante, el eliminador permanece sin cambios y todavía sabe cómo liberar una
Thing
.
Que es lo que hace cuando el
voidPtr
queda fuera de alcance.
Esta pregunta ya tiene una respuesta aquí:
- ¿Por qué std :: shared_ptr <void> funciona 6 respuestas
Escribí el siguiente código para ver cómo se comportaría un
shared_ptr<void>
cuando es la última referencia a
shared_ptr<Thing>
y se destruye.
#include <iostream>
#include <string>
#include <memory>
using namespace std;
struct Thing{
~Thing(){
cout<<"Destroyed/n";
}
int data;
};
int main(){
{
shared_ptr<void> voidPtr;
{
shared_ptr<Thing> thingPtr = make_shared<Thing>();
voidPtr = thingPtr;
}
cout<<"thingPtr is dead/n";
}
cout<<"voidPtr is dead/n";
return 0;
}
Qué salidas:
thingPtr is dead
Destroyed
voidPtr is dead
Se comporta de la manera que me
gusta
, pero es totalmente inesperado y me gustaría entender qué está pasando aquí.
El puntero compartido inicial ya no existe, es solo un
shared_ptr<void>
al final.
Por lo tanto, esperaría que este puntero compartido actúe como si estuviera sosteniendo un
void*
y no tenga idea de
Thing::~Thing()
, pero lo llama.
Esto es por diseño, ¿verdad?
¿Cómo está logrando esto el puntero compartido vacío?
shared_ptr
solo sabe cómo manejar un objeto de administración con una interfaz conocida.
Ese objeto de administración proporciona dos recuentos de referencia (débil para sí mismo, fuerte para el objeto administrado), así como también contiene el eliminador (el acceso aparte de llamar solo se proporciona si se conoce el tipo) y el puntero que se eliminará (privado) .
A qué tipo y objeto
shared_ptr
el
shared_ptr
es una preocupación completamente separada del objeto de administración que utiliza, aunque por razones de cordura no debería
shared_ptr
más.