¿Cuál es el comportamiento de “eliminar” con objetos de stack?

int main() { Class_Name t; Class_Name * p = &t; delete p; return 0; } 

Este código se ejecuta bien con 2 destructores que se llaman? ¿Cómo funciona eliminar con objetos de stack? Es el comportamiento indefinido?

Te encuentras con un comportamiento indefinido.

Estándar (N3690) 5.3.5 [expr.delete] / 2

Si el operando tiene un tipo de clase, el operando se convierte a un tipo de puntero llamando a la función de conversión mencionada anteriormente, y el operando convertido se usa en lugar del operando original para el rest de esta sección. En la primera alternativa (eliminar objeto), el valor del operando de eliminar puede ser un valor de puntero nulo, un puntero a un objeto que no sea de matriz creado por una nueva expresión previa o un puntero a un subobjeto (1.8) que represente una clase base de tal objeto (Cláusula 10). Si no, el comportamiento no está definido.

No tiene un puntero nulo, ni tiene un Objeto previamente asignado con nuevo, por lo que el comportamiento no está definido.

Nota: incluso cuando intentas hacer

 int main() { Class_Name t; t.~Class_Name() return 0; } 

sería un comportamiento indefinido. Aunque no tiene una eliminación, simplemente porque llama explícitamente al destructor de un objeto con duración de almacenamiento automático. Lo que significa que se llamaría al destructor dos veces, una vez cuando se lo llama explícitamente, la segunda vez que se abandona su scope.

Estándar 12.4 [class.dtor] / 15

Una vez que se invoca un destructor para un objeto, el objeto ya no existe; el comportamiento no está definido si se invoca el destructor para un objeto cuya vida útil ha finalizado (3.8). [ Ejemplo: si el destructor para un objeto automático se invoca explícitamente, y el bloque se deja posteriormente de una manera que ordinariamente invocaría la destrucción implícita del objeto, el comportamiento no está definido. -Final ejemplo ]

La mayoría de las veces, intentar hacer algo como eso (afortunadamente) provocaría un colapso. Con un deconstructor trivial puede que tengas (mala) suerte y no pase nada.

Poco de nitpick de terminología aquí: el estándar de C ++ no habla de objetos de stack versus de montón, siempre habla de duración de almacenamiento automático frente a dynamic, respectivamente. Como también puedes ver en la cita anterior.


Siempre debe seguir las pautas generales:

  • Para los objetos asignados a la stack no se realiza ninguna liberación / eliminación explícita (los destructores se llaman automáticamente).
  • Para cada new debería haber una delete correspondiente
  • Para cada new[] debe haber una delete[] correspondiente delete[]
  • Para cada malloc o calloc debe haber un free correspondiente