После throw 2 начинается раскрутка стека, и деструктор B выпускает новое исключение. Это вызывает std::terminate до входа в catch, несмотря на noexcept(false).
std::terminate вызывается при исключении в деструкторе
После throw 2 начинается раскрутка стека, и деструктор B выпускает новое исключение. Это вызывает std::terminate до входа в catch, несмотря на noexcept(false).
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
При каких условиях выполнение кода внутри блока try приводит к автоматическому вызову std::terminate?
void test_destructor()
{
struct B {
~B() noexcept(false) {
throw 1;
}
};
try {
B obj;
throw 2; // рассматриваемый случай
} catch (...) {
}
}
Ответ
После throw 2 начинается раскрутка стека, и деструктор B выпускает новое исключение. Это вызывает std::terminate до входа в catch, несмотря на noexcept(false).
noexcept(false) означает, что функция в принципе может завершаться исключением. Но деструктор, вызванный механизмом обработки уже активного исключения, не должен выпускать другое исключение наружу.
Если убрать throw 2, объект будет разрушаться при обычном выходе из блока, и throw 1 из этого явно бросающего деструктора сможет попасть в catch. Для безопасной очистки ошибку обычно обрабатывают внутри деструктора или выносят в отдельный метод.