Je suis bien conscient du fait qu'il ne faut pas lancer d'exception dans le destructeur.
Mais dans le cadre de ma prise en main sur ce concept, j'ai codé cet exemple: -
#include <iostream>
using namespace std;
class A {
private:
int i;
public:
A()
{
i = 10;
}
~A()
{
throw 30;
}
};
int main(){
try{
A();
throw 10;
}
catch (int i){
cout << i << endl;
cout << "exception caught" << endl;
}
}
Selon ma compréhension, ce programme devrait être terminé en appelant std :: terminate () car il y aura deux exceptions en même temps. Mais, ce programme donne la sortie suivante: -
30
exception caught
Quelqu'un peut-il s'il vous plaît m'expliquer la logique derrière cela pour expliquer pourquoi cela ne se termine pas?
std::terminate
Sera appelé si une exception est levée pendant le déroulement de la pile . Cela signifie que si une exception est appelée tandis qu'une autre exception est gérée, alors std::terminate
Sera appelé.
Dans votre exemple, cela ne se produit pas - A();
construira et détruira immédiatement une instance de A
. Le throw 30
Sera alors correctement capturé.
Changer votre code pour:
int main(){
try{
A a; // begin `a` lifetime
throw 10; // | throw #0
// | end `a` lifetime
// throw #1
}
catch(int i){
cout<<i<<endl;
cout<<"exception caught"<<endl;
}
}
garantira que std::terminate
sera appelé. Dans ce cas, a
sera détruit et lancera pendant qu'une autre exception est gérée .
Information additionnelle:
Notez que en C++ 11 et supérieur , votre extrait de code appellera std::terminate
Et vous avertira:
main.cpp: Dans le destructeur ‘A :: ~ A ()’:
main.cpp: 16: 15: avertissement: throw appellera toujours terminate () [-Wterminate]
throw 30; ^~
main.cpp: 16: 15: note: dans les destructeurs C++ 11 par défaut à noexcept
terminate appelé après avoir lancé une instance de 'int'
bash: ligne 7: 1505 abandonné (core dumpé) ./a.out
Comme on le voit dans la sortie du compilateur, puisque les destructeurs C++ 11 sont implicitement noexcept(true)
. Si vous souhaitez empêcher ce comportement, vous pouvez simplement les marquer comme noexcept(false)
. Exemple:
~A() noexcept(false)
{
throw 30;
}
Dans votre exemple, A()
construit une variable temporaire pour A
puis la détruit immédiatement. Ainsi throw 10;
N'est jamais exécuté.
L'instruction throw
en cours d'exécution se trouve dans le destructeur de A
. Lors de l'exécution de A::~A()
, le programme ne se déroule pas (c'est-à-dire nettoie l'état d'une exception) à ce stade. Voir "Destructeurs qui lancent" par exemple.