web-dev-qa-db-fra.com

Les destructeurs sont-ils appelés après un lancer en C ++?

J'ai exécuté un exemple de programme et en effet des destructeurs pour les objets alloués à la pile sont appelés, mais est-ce garanti par la norme?

47
Luchian Grigore

Oui, c'est garanti (à condition que l'exception soit interceptée), jusqu'à l'ordre dans lequel les destructeurs sont invoqués:

C++ 11 15.2 Constructeurs et destructeurs [except.ctor]

1 Lorsque le contrôle passe d'une expression de jet à un gestionnaire, des destructeurs sont appelés pour tous les objets automatiques construits depuis l'entrée du bloc try. Les objets automatiques sont détruits dans l'ordre inverse de l'achèvement de leur construction.

De plus, si l'exception est levée pendant la construction de l'objet, les sous-objets de l'objet partiellement construit sont garantis comme étant correctement détruits:

2 Un objet de n'importe quelle durée de stockage dont l'initialisation ou la destruction se termine par une exception aura des destructeurs exécutés pour tous ses sous-objets entièrement construits (à l'exclusion des membres variant d'une classe de type union), c'est-à-dire pour les sous-objets pour lesquels le constructeur principal (12.6.2) a terminé son exécution et le destructeur n'a pas encore commencé son exécution. De même, si le constructeur non délégué pour un objet a terminé son exécution et qu'un constructeur délégué pour cet objet se termine avec une exception, le destructeur de l'objet sera appelé. Si l'objet a été alloué dans une nouvelle expression, la fonction de désallocation correspondante (3.7.4.2, 5.3.4, 12.5), le cas échéant, est appelée pour libérer le stockage occupé par l'objet.

L'ensemble de ce processus est appelé "déroulement de pile":

3 Le processus d'appel de destructeurs pour des objets automatiques construits sur le chemin d'un bloc d'essai à une expression de lancement est appelé "déroulement de pile". Si un destructeur appelé pendant le déroulement de la pile se termine avec une exception, std :: terminate est appelé (15.5.1).

Le déroulement de la pile constitue la base de la technique largement utilisée appelée Resource Acquisition Is Initialization (RAII) .

Notez que le déroulement de la pile n'est pas nécessairement effectué si l'exception n'est pas interceptée. Dans ce cas, c'est à l'implémentation que le déroulement de la pile soit effectué. Mais que le déroulement de la pile soit effectué ou non, dans ce cas, vous êtes assuré d'un dernier appel à std::terminate.

C++ 11 15.5.1 La fonction std :: terminate () [except.terminate]

2… Dans le cas où aucun gestionnaire de correspondance n'est trouvé, il est défini par l'implémentation que la pile soit déroulée ou non avant l'appel de std::terminate().

57
NPE

Oui, les destructeurs sont garantis lors du déroulement de la pile, y compris le déroulement en raison d'une exception levée. Il n'y a que quelques astuces avec des exceptions dont vous devez vous souvenir:

  • Le destructeur de la classe n'est pas appelé si une exception est levée dans son constructeur.
  • L'exception est automatiquement renvoyée si elle est interceptée dans le bloc de capture de la liste d'initialisation de la construction.
6
user405725

Si un lancer est intercepté, les opérations cpp se poursuivent normalement. Cela inclut les destructeurs et l'éclatement de la pile. Cependant, si l'exception n'est pas interceptée, l'éclatement de la pile n'est pas garanti.

De plus, un lancer nu ou un lancer vide ne peut pas être intercepté par mon compilateur mobile.

exemple:

#include <Jav/report.h>

int main()
{
 try { throw; }
 catch(...) { rep("I bet this is not caught"); }
 }
1
Javene CPP McGowan