Ответ 1
std::terminate
будет вызываться, если исключение генерируется во время разматывания стека. Это означает, что если вызывается исключение, когда обрабатывается другое исключение, тогда будет вызываться std::terminate
.
В вашем примере этого не произойдет - A();
построит и немедленно уничтожит экземпляр A
. Затем throw 30
будет правильно поймано.
Изменение кода на:
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;
}
}
гарантирует, что будет вызываться std::terminate
. В этом случае A
будет уничтожен и будет бросать , пока обрабатывается другое исключение.
Дополнительная информация:
Обратите внимание, что в С++ 11 и выше, ваш фрагмент кода вызовет std::terminate
и предоставит вам предупреждение:
main.cpp: В деструкторе 'A:: ~ A():
main.cpp: 16: 15: предупреждение: throw всегда будет вызывать terminate() [-Wterminate]
throw 30; ^~
main.cpp: 16: 15: примечание: в дескрипторах С++ 11 по умолчанию noexcept
завершение вызова после вызова экземпляра 'int'
bash: строка 7: 1505 Отменено (ядро сбрасывается)./a.out
Как видно из вывода компилятора, поскольку С++ 11 деструкторы неявно noexcept(true)
. Если вы хотите предотвратить это поведение, вы можете просто отметить их как noexcept(false)
. Пример:
~A() noexcept(false)
{
throw 30;
}