c++ - Es "borrar esto" una mala idea?
memory-management (5)
Posible duplicado:
¿Es segurodelete this
?
He estado haciendo un pequeño trabajo en una clase que está diseñada para actuar como un nodo en una lista vinculada, y pensé que le daría a la clase su propia función de eliminación en lugar de que la clase administradora lo hiciera. Así que básicamente va así:
void Class::Delete() {
//Some cleanup code before deleting the object
delete this;
}
Ahora he probado esto y parece que funciona bien, pero he tenido un problema en el pasado donde los objetos han estado en medio de ejecutar el código, se han eliminado, y luego obviamente se estrelló el programa al tratar de usar un no más. -existente objeto.
Ya que "eliminar esto" está justo al final de la función, obviamente sale de la función y funciona bien, pero ¿es este tipo de práctica una mala idea? ¿Podría esto alguna vez estallar en mi cara si no tengo cuidado?
El FAQlite responde esto bastante bien:
Mientras tenga cuidado, está bien que un objeto se suicide (elimínelo).
Así es como defino "cuidado":
- Debe estar absolutamente seguro al 100% de que este objeto se asignó a través de nuevo (no por nuevo [], ni por la colocación de un nuevo, ni un objeto local en la pila, ni un miembro global, ni un miembro de otro objeto; sino simplemente ordinario nuevo).
- Debe estar absolutamente seguro de que su función miembro será la última función miembro invocada en este objeto.
- Debe estar absolutamente seguro de que el resto de su función de miembro (después de la eliminación de esta línea) no toque ninguna parte de este objeto (incluida la llamada a otras funciones de miembro o tocar cualquier miembro de datos).
- Debe estar absolutamente seguro al 100% de que nadie toque el mismo puntero después de eliminar esta línea. En otras palabras, no debe examinarlo, compararlo con otro puntero, compararlo con NULL, imprimirlo, lanzarlo, hacer nada con él.
Naturalmente, las advertencias habituales se aplican en los casos en que su puntero es un puntero a una clase base cuando no tiene un destructor virtual.
Básicamente, debe tener el mismo cuidado que con la delete
de cualquier otro puntero. Sin embargo, hay más áreas en las que las cosas pueden ir mal con una función miembro que se suicida, en comparación con un indicador explícitamente declarado.
El uso de delete this
es una mala idea si uno no está seguro de los inconvenientes y cómo solucionarlos.
Una vez que llames a delete this
el destructor del objeto será invocado y la memoria asignada dinámicamente se liberará.
Si el objeto no se asignó usando new
, será un Undefined behaviour
.
Si se accede a alguno de los miembros de datos del objeto o funciones virtuales después de delete this
, el comportamiento será de nuevo Undefined Behavior
.
Probablemente, es mejor evitar delete this
dado lo anterior.
En realidad, es un lenguaje frecuente, y tan seguro como cualquier eliminación. Al igual que con todas las eliminaciones, debe asegurarse de que ningún otro código intente acceder al objeto y asegurarse de que el objeto se haya asignado dinámicamente. Normalmente, sin embargo, esto último no es un problema, ya que el idioma solo es relevante para los objetos que tienen una vida útil determinada por la semántica del objeto, y dichos objetos siempre se asignan de forma dinámica. Al encontrar todos los punteros también, el objeto puede ser un problema (ya sea que se use delete this
o no); por lo general, se utilizará alguna forma del patrón de observador para notificar a todas las partes interesadas que el objeto dejará de existir.
Hay una forma sencilla de hacer lo mismo que no implica un comportamiento indefinido:
void Class::Delete() {
//Some cleanup code before deleting the object
std::auto_ptr delete_me(this);
}
La forma idiomática de hacerlo en C ++ es colocando el código de limpieza en el destructor y luego dejándolo llamar automáticamente cuando eliminas el objeto.
Class::~Class() {
do_cleanup();
}
void ManagingClass::deleteNode(Class* instance) {
delete instance; //here the destructor gets called and memory gets freed
}