c++ - ¿Se debería llamar a "eliminar esto" desde un método miembro?
self-destruction (12)
Acabo de leer este article y quería el consejo de SO:
Q: Debería delete this;
ser llamado desde dentro de un método miembro?
-
delete this
no se puede llamar desde una función no miembro :) - Es una mala idea hacer hasta que entiendas sus consecuencias.
Algunas bibliotecas de subprocesos lo utilizan cuando implementan una destrucción automática en la terminación del subproceso
void Thread::threadFunc()
{
doRun();
if(this->destroyOnExit == true)
delete this;
}
Aunque no estaba directamente relacionado con este hilo, quería aclarar esto. Me hicieron una pregunta que dada una situación:
int* a = new int ;
int* b = a ;
delete a;
Ahora es la siguiente afirmación segura?
cout<<*b ;
Mi respuesta: después de eliminar a, la ubicación señalada por a ha sido marcada para su eliminación y en cualquier momento puede asignarse a otro objeto. Por lo tanto, acceder al valor utilizando b no es seguro ya que puede modificarse después de ser asignado a algún otro objeto.
Nota: No hay votaciones por favor, esto es solo una aclaración.
Creo que hay realmente 2 preguntas aquí
¿Se puede eliminar esto de forma válida desde un método miembro?
Sí. Esto es legal siempre y cuando sea muy cuidadoso con el uso.
¿Debería eliminarse este uso dentro de un método miembro?
En casos muy específicos esto es necesario. Ciertos tipos de punteros inteligentes, por ejemplo, utilizan la delete this
patrón para eliminar el puntero. Ejemplos: estilo CComPtr<>
.
Sin embargo, aparte de los punteros inteligentes, debe evitarse a menos que tenga una buena razón para hacerlo. Incluso entonces, reconsideraría cuidadosamente mi escenario y vería si había alguna forma de evitarlo.
Esto fue utilizado a menudo en los días de MFC. IIRC el último mensaje que recibe una ventana es WM_NCDESTROY
, momento en el que puedes llamar a delete this
, asumiendo que eres un sádico, por supuesto (aunque MFC lo hizo a veces, creo).
No sin una muy buena razón para hacerlo.
El problema es que cuando llama a delete this
en una función miembro, está creando un efecto secundario desagradable: la persona que llama todavía tiene una referencia a su instancia que ahora es completamente inválida.
Probablemente este no sea un comportamiento esperado, por lo que fácilmente podría llevar a errores desagradables.
Dicho esto, hay ocasiones en que esto es apropiado (he visto algunos esquemas de administración de memoria, con ciertas bibliotecas, donde crea explícitamente métodos en las clases que se eliminan a sí mismos, principalmente para la interoperabilidad del idioma). En general, creo que es una mala práctica, sin embargo.
Normalmente esta es una mala idea, pero ocasionalmente es útil.
Es perfectamente seguro siempre y cuando no utilice ninguna variable miembro después de eliminar, y siempre que los clientes que llaman a este método entiendan que puede eliminar el objeto.
Un buen ejemplo de cuando esto es útil es si su clase emplea el conteo de referencias:
void Ref() {
m_References++;
}
void Deref() {
m_References--;
if (m_References == 0) {
delete this;
}
}
Preparándose para los votos a la baja.
En caso de que : No.
Puede técnicamente : sí
¿Es una buena idea ? Absolutamente no.
¿Hay alguna situación útil ? Por supuesto. Si eres de C ++, foo es extremadamente fuerte. Pero la mayoría de la gente no es tan buena. Solo haga esto si tiene un equipo de personas trabajando con usted que pueda hacer una revisión decente del código.
Por que
No hay forma de que un objeto sepa que se ha asignado dinámicamente (y por lo tanto necesita eliminarse) o que es un objeto normal (y, por lo tanto, no debe eliminarse) y, por lo tanto, cómo puede decidirse el clima en que debe eliminarse. Por lo tanto, si un objeto se está eliminando a sí mismo, en mi opinión, hay algo terriblemente mal con el diseño.
Si tiene un objeto que necesita administración, debe escribir un objeto separado para realizar la administración (por lo tanto, punteros inteligentes). Deje que el objeto haga lo que es bueno y luego separe la gestión del objeto en otro objeto.
Puede hacerlo, siempre que sea el último elemento en una función miembro, y que, después de regresar, se olvide de que el objeto haya existido ... pero sí, al igual que ese artículo pregunta ... ¿Por qué querría hacer esto? No sé lo que dice la norma, pero me da una sensación extraña: P
Supongo que esto es un poco como si alguna vez usara una declaración GOTO, y yo personalmente uso GOTO para limpiar los recursos en C a veces, especialmente en condiciones excepcionales.
Me pregunto cuáles son las implicaciones del estado compartido (declaración confusa que conozco): P
Sí, hay algunos casos donde es común.
Recuento de referencias:
void release()
{
cnt--;
if (cnt == 0)
delete this;
}
Programación GUI. En algunos marcos, cuando un usuario cierra una ventana, es común que la ventana se elimine a sí misma.
Sí, puedes y here''s una buena explicación de cuándo y por qué.
Sí. Como dicen todas las respuestas, si está 100% seguro de que los datos de la clase no se utilizarán después de la delete this
se llamará.
Por ejemplo, en un proyecto:
void Test()
MyClass * Someclass = new MyClass;
SomeClass->DoYourThing();
SomeClass->KillYourself();
return;
void MyClass::DoYourThing() { return; }
void MyClass::KillYourself() {delete this;}
Explicación muy simplista, el proyecto utilizado delete this;
como parte de la gestión de memoria para objetos de ese tipo; su constructor los agregó a una lista privada de clases de ese tipo en uso, y se eliminaron a sí mismos de esa lista cuando fueron destruidos y luego se eliminaron a sí mismos (esto no estaba en un destructor). Todos los objetos de esa clase que no se habían eliminado cuando el programa llegó a su punto final, todos tenían su equivalente KillYourself()
llamado desde una función miembro estática CleanYourselves()