std::terminate вызывается при исключении в деструкторе

После throw 2 начинается раскрутка стека, и деструктор B выпускает новое исключение. Это вызывает std::terminate до входа в catch, несмотря на noexcept(false).

Короткий ответ

Что ответить на собеседовании

После 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. Для безопасной очистки ошибку обычно обрабатывают внутри деструктора или выносят в отдельный метод.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее