¿Se llaman los destructores después de un lanzamiento en C ++?

Ejecuté un progtwig de ejemplo y, de hecho, se llaman destructores para los objetos asignados a la stack, pero ¿está esto garantizado por el estándar?

Sí, está garantizado (siempre que se capture la excepción), hasta el orden en que se invocan los destructores:

C ++ 11 15.2 Constructores y destructores [excepto.ctor]

1 A medida que el control pasa de una expresión de proyección a un manejador, se invocan los destructores para todos los objetos automáticos construidos desde que se ingresó el bloque de prueba. Los objetos automáticos se destruyen en el orden inverso de la finalización de su construcción.

Además, si se lanza la excepción durante la construcción del objeto, se garantiza que los subobjetos del objeto parcialmente construido se destruirán correctamente:

2 Un objeto de cualquier duración de almacenamiento cuya inicialización o destrucción sea terminada por una excepción tendrá destructores ejecutados para todos sus subobjetos completamente construidos (excluyendo los miembros variantes de una clase tipo unión), es decir, para subobjetos para los cuales el constructor principal (12.6.2) ha completado la ejecución y el destructor aún no ha comenzado la ejecución. De forma similar, si el constructor no delegante para un objeto ha completado la ejecución y un constructor delegante para ese objeto sale con una excepción, se invocará el destructor del objeto. Si el objeto se asignó en una nueva expresión, se llama a la función de desasignación correspondiente (3.7.4.2, 5.3.4, 12.5), si la hay, para liberar el almacenamiento ocupado por el objeto.

Todo este proceso se conoce como “desenrollado de la stack”:

3 El proceso de invocación de destructores para objetos automáticos construidos en la ruta desde un bloque try a una expresión throw se denomina “desenrollado de stack”. Si un destructor llamado durante el desenrollado de stack sale con una excepción, se llama std :: terminate (15.5. 1).

El desenrollado de la stack forma la base de la técnica ampliamente utilizada llamada Inicialización de adquisición de recursos (RAII) .

Tenga en cuenta que el desenrollado de la stack no se realiza necesariamente si no se detecta la excepción. En este caso, depende de la implementación si se realiza el desenrollado de la stack. Pero ya sea que se complete o no el desenrollado de la stack, en este caso se garantiza una llamada final a std::terminate .

C ++ 11 15.5.1 La función std :: terminate () [except.terminate]

2 … En la situación en la que no se encuentra ningún controlador coincidente, se define su implementación independientemente de si la stack se desenrolla o no antes de llamar a std::terminate() .

Sí, se garantiza la invocación de destructores en el desenrollado de la stack, incluido el desenrollado debido a la excepción lanzada. Hay solo algunos trucos con excepciones que debes recordar:

  • Destructor de la clase no se llama si se arroja una excepción en su constructor.
  • La excepción se vuelve a lanzar automáticamente si se detecta en el bloque catch de la lista de inicialización de la construcción.