c++ boost shared-ptr boost-smart-ptr

c++ - Eliminación explícita de un shared_ptr



boost shared-ptr (5)

No puede forzar su cuenta de referencia a cero, no.

Piensa en lo que se necesitaría para que eso funcione. Debería ir a cada lugar donde se utiliza shared_ptr y borrarlo.

Si forzó el puntero compartido para eliminar y establecerlo en NULL, sería como un weak_ptr. Sin embargo, todos los lugares del código que utilizan ese shared_ptr no están listos para eso y esperan tener un puntero válido. No tienen ninguna razón para verificar NULL, y esos pedazos de código se bloquearían.

Pregunta simple aquí: ¿puedes eliminar un boost::shared_ptr ? ¿Deberías alguna vez?

Aclarando, no me refiero a eliminar el puntero sostenido por shared_ptr . shared_ptr decir el mismo shared_ptr . Sé que la mayoría de la gente sugiere no hacerlo, así que me preguntaba si está bien hacerlo explícitamente.


Tu pregunta no está clara. Si ha asignado un shared_ptr dinámicamente, puede delete cuando lo desee.

Pero si estás preguntando si puedes eliminar cualquier objeto que sea administrado por shared_ptr , entonces la respuesta es ... depende. Si shared_ptr::unique devuelve true, la llamada shared_ptr::reset eliminará el objeto gestionado. Sin embargo, si shared_ptr::unique devuelve false, significa que hay más de un shared_ptr compartiendo la propiedad de ese objeto. En este caso, una llamada a reset solo dará como resultado que el recuento de referencia disminuya en 1, la eliminación real del objeto tendrá lugar cuando el último shared_ptr que administre ese objeto salga del alcance o se reset .

EDITAR:
Después de su edición, parece que está pidiendo eliminar un shared_ptr dinámicamente asignado. Algo como esto:

auto sp = new boost::shared_ptr<int>( new int(42) ); // do something with sp delete sp;

Esto está permitido y funcionará como se espera, aunque sería un caso de uso inusual. La única advertencia es que si entre la asignación y eliminación de sp se crea otro shared_ptr que comparte la propiedad del objeto, al eliminar sp no se eliminará el objeto, eso solo ocurrirá cuando el recuento de referencias para el objeto vaya a 0 .


[Editar: puede delete un shared_ptr si y solo si fue creado con new , igual que con cualquier otro tipo. No puedo pensar por qué shared_ptr un shared_ptr con new , pero no hay nada que te detenga.]

Bueno, podrías escribir delete ptr.get(); .

Hacerlo conduce casi inevitablemente a un comportamiento indefinido, ya sea cuando los otros propietarios compartidos utilizan su shared_ptr para acceder al objeto ahora eliminado, o se destruye el último shared_ptr del objeto, y el objeto se elimina de nuevo.

Entonces no, no deberías.

El propósito de shared_ptr es administrar un objeto que ninguna "persona" tiene el derecho o la responsabilidad de eliminar, ya que podría haber otros que comparten la propiedad. Entonces tampoco deberías quererlo nunca.


Si quiere simular la disminución del conteo, puede hacerlo manualmente en el montón como lo hizo:

int main(void) { std::shared_ptr<std::string>* sp = new std::shared_ptr<std::string>(std::make_shared<std::string>(std::string("test"))); std::shared_ptr<std::string>* sp2 = new std::shared_ptr<std::string>(*sp); delete sp; std::cout << *(*sp2) << std::endl; // test return 0; }

O en la pila usando std::shared_ptr::reset() así:

int main(void) { std::shared_ptr<std::string> p = std::make_shared<std::string>(std::string("test")); std::shared_ptr<std::string> p2 = p; p.reset(); std::cout << *p2 << std::endl; // test return 0; }

Pero no es tan útil.


La eliminación manual es útil en algunos (¿muy?) Raros casos.

¡Además de eliminar explícitamente, a veces TIENES que destruir explícitamente un puntero compartido cuando lo ''borras''!

Las cosas pueden volverse raras cuando interactúan con el código C, pasando un shared_ptr como un valor opaco.

Por ejemplo, tengo lo siguiente para pasar objetos desde y hacia el lenguaje de escritura Lua que está escrito en C. (www.lua.org)

static void push( lua_State *L, std::shared_ptr<T> sp ) { if( sp == nullptr ) { lua_pushnil( L ); return; } // This is basically malloc from C++ point of view. void *ud = lua_newuserdata( L, sizeof(std::shared_ptr<T>)); // Copy constructor, bumps ref count. new(ud) std::shared_ptr<T>( sp ); luaL_setmetatable( L, B::class_name ); }

Entonces eso es un shared_ptr en alguna memoria malloc''d. El reverso es este ... (la configuración se llamará justo antes de que la basura de Lua recolecte un objeto y ''lo libere'').

static int destroy( lua_State *L ) { // Grab opaque pointer void* ud = luaL_checkudata( L, 1, B::class_name ); std::shared_ptr<T> *sp = static_cast<std::shared_ptr<T>*>(ud); // Explicitly called, as this was ''placement new''d // Decrements the ref count sp->~shared_ptr(); return 0; }