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;
}