c++ - ¿Para qué sirve "eliminar esto"?
memory-management destructor (4)
"borrar esto" se usa comúnmente para objetos contados por ref. Para un objeto contado por ref, la decisión de cuándo eliminar generalmente se coloca en el objeto mismo. Aquí hay un ejemplo de cómo se vería un método de liberación [1].
int MyRefCountedObject::Release() {
_refCount--;
if ( 0 == _refCount ) {
delete this;
return 0;
}
return _refCount;
}
Los objetos ATL COM son un excelente ejemplo de este patrón.
[1] Sí, me doy cuenta de que esto no es seguro para subprocesos.
Hoy, he visto algún código heredado. En el destructor hay una declaración como " delete this
". Creo que esta llamada será recursiva. ¿Por qué está funcionando?
Hice una búsqueda rápida en Y !, encontré que si hay una necesidad de restringir al usuario para crear el objeto de pila, podemos hacer que destructor sea privado y proporcionar una interfaz para eliminar la instancia. En la interfaz proporcionada, tenemos que llamar eliminar en este puntero.
¿Hay alguna otra situación para usar tales declaraciones?
En una lista doblemente vinculada, es posible eliminar un nodo sin hacer referencia a ninguna estructura externa, como el objeto de "lista" de alto nivel. Esto hace que sea razonable que cada nodo maneje su propia desasignación (potencialmente asociado con un método estático complementario para manejar la asignación inicial desde el mismo grupo de memoria). En esta situación, podría tener sentido que el objeto nodo se elimine solo (cuando lo solicite el usuario).
void RemoveAndDeallocate()
{
LinkedListNode *current_prev = prev, *current_next = next;
current_prev->next = current_next;
current_next->prev = current_prev;
delete this;
}
Sin embargo, también es razonable que un nodo se desvincula de una lista y se vincule a otra lista, sin desasignar ninguna memoria, por lo que no es deseable que una sola operación de eliminación libere incondicionalmente la memoria.
Se consideraron buenas razones para hacerlo en los primeros días de C ++. Por ejemplo, la eliminación automática de un objeto contado por ref (como dice JaredPar). Hasta donde yo sé, todos han sido una mala idea a largo plazo.
delete this
no es válido en un destructor. Se puede usar en otro lugar. Pero rara vez es una buena idea. El framework wxWidgets
usa para su clase de subprocesos. Tiene un modo donde, cuando el hilo termina la ejecución, libera automáticamente los recursos del sistema y el mismo (el objeto wxThread). Me resulta muy molesto, porque desde el exterior, no se puede saber si es válido referirlo o no: ya no se puede llamar a una función como IsValid
porque el objeto no existe. Eso huele como el problema principal con delete this
, aparte del problema de que no se puede usar para objetos no dinámicos.
Si lo hace, asegúrese de no tocar ningún miembro de datos, ni llamar a ninguna función miembro más sobre el objeto que eliminó de esa manera. Lo mejor es hacerlo como la última declaración en una función no virtual, protegida o privada. Llamar a delete también es válido en una función virtual y / o pública, pero restringiría la visibilidad del método al hacerlo.
Las preguntas frecuentes de C ++ tienen una entrada sobre eso. Cita estándar de C ++ en mi reclamo anterior ( 3.8p5
):
Antes de que se haya iniciado el tiempo de vida de un objeto pero después de que se haya asignado el almacenamiento que ocupará el objeto o, una vez que haya finalizado el tiempo de vida del objeto y antes de que se reutilice o libere el objeto ocupado, cualquier puntero que haga referencia al almacenamiento la ubicación donde se ubicará o se ubicará el objeto se puede usar, pero solo de manera limitada. [...] Si el objeto será o era de un tipo de clase con un destructor no trivial, y el puntero se utiliza como el operando de una expresión de eliminación, el programa tiene un comportamiento indefinido.
La vida útil finaliza cuando el destructor del objeto comienza la ejecución. Tenga en cuenta que hay excepciones a las reglas que vienen después de ese párrafo para objetos en construcción y destrucción (se le permite acceder a miembros de datos no estáticos, por ejemplo), detallados en 12.7
.