362просмотров
15 мая 2025 г.
Score: 398
Нам всегда говорили, что бросать исключения из деструктора это плохая идея. Один из примеров плохого результата - это раскручивание стека при обработке исключения, когда вызываемые деструкторы приводят к повторному исключению, которое кроме как вызовом terminate() толком не обработаешь. Но что, если выбросить исключение очень хочется, ведь мы сделаем всё "аккуратно"? Давайте посмотрим на такой код:
#include <iostream> struct ThrowsInDtor
{ ~ThrowsInDtor() { std::cout << "~ThrowsInDtor" << std::endl; throw std::runtime_error("holy..."); }
}; int main(int argc, char* argv<::>)
{ try { ThrowsInDtor dtor; } catch (const std::runtime_error& ex) { std::cout << "ex: " << ex.what() << std::endl; } return 0;
} Что тут может пойти не так, вроде же всё ОК? Одно исключение, мы его ловим. По факту, данный код приведет к вызову terminate(), так как все деструкторы по-умолчанию неявно помечены как noexcept, то есть не выбрасывающие исключений. Если очень сильно хочется вернуться во времена до C++11, то помечаем деструктор как noexcept(false) и получаем наше исключение (не понятно только зачем):
~ThrowsInDtor() noexcept(false)