c++ shared-ptr void

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í:

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.