Поведение деструктора при генерации исключения

В стандартном C++ std::exception не имеет конструктора от строки, поэтому исходник непереносим и обычно не компилируется. Если заменить его на std::runtime_error, возникнет std::terminate.

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

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

В стандартном C++ std::exception не имеет конструктора от строки, поэтому исходник непереносим и обычно не компилируется. Если заменить его на std::runtime_error, возникнет std::terminate.

Подробный разбор

Ответ с пояснениями

Условие

Какой результат будет получен при запуске следующего кода?

void destructor_check()
{
    struct A {
        ~A() noexcept(false) {
            throw 1;
        }
    };

    try {
        A a;
        throw std::exception("~("); // активное исключение
    } catch (...) {
    }
}

Ответ

В стандартном C++ std::exception не имеет конструктора от строки, поэтому исходник непереносим и обычно не компилируется. Если заменить его на std::runtime_error, возникнет std::terminate.

После исправления внешнего throw начинается раскрутка стека. Деструктор A выбрасывает int до перехода в catch, то есть выпускает второе исключение во время обработки первого.

noexcept(false) разрешает деструктору выбрасывать при обычном вызове, но не отменяет правило завершения при таком двойном исключении. Пустой catch снаружи не спасает. Возможную ошибку очистки нужно перехватить внутри деструктора либо сообщать через отдельную явную операцию.

Источник: eel.is.

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

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

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

Подробнее