Ответ 1
Исходный код throw;
, когда вам нечего реконструировать. Это вызывает вызов std::terminate
; стек не разматывается (и, следовательно, деструкторы не запускаются).
Ваш новый код генерирует исключение без его обработки. В этом случае, если стек разматывается, он определяется реализацией, поэтому он все еще отлично соответствует terminate()
сразу. [except.terminate], акцент мой:
В некоторых ситуациях обработка исключений должна быть отменена за меньшую тонкие методы обработки ошибок. [Примечание: Эти ситуации:
- когда механизм обработки исключений после завершения инициализации объекта исключения, но до активации обработчик для исключения (15.1), вызывает функцию, которая выходит через исключение или
- , когда механизм обработки исключений не может найти обработчик для созданного исключения (15.3) или
- когда поиск обработчика (15.3) встречает внешний блок функции с noexcept-спецификацией, которая не позволяет исключение (15.4) или
- когда уничтожение объекта во время разматывания стека (15.2) завершается путем исключения исключения или
- когда инициализация нелокальной переменной со статической или длительностью хранения потоков (3.6.2) завершается через исключение или
- когда уничтожение объекта со статикой или продолжительностью хранения потоков завершается с помощью исключения (3.6.3) или
- когда выполнение функции, зарегистрированной в
std::atexit
илиstd::at_quick_exit
, завершается с помощью исключения (18.5) или- , когда выражение throw (5.17) без операнда пытается перестроить исключение и исключение не обрабатывается (15.1), или
- когда
std::unexpected
завершается за исключением типа, который не допускается ранее описанной спецификацией исключения, и std:: bad_exception не входит в эту спецификацию исключения (15.5.2) или- когда вызывается вызванный по умолчанию обработчик исключений по умолчанию (D.8.1) или
- когда вызывается функция
std::nested_exception::rethrow_nested
для объекта, который не исключил исключение (18.8.6), или- когда выполнение начальной функции потока завершается через исключение (30.3.1.2) или
- когда деструктор или оператор назначения копирования вызывается на объект типа
std::thread
, который ссылается на соединяемую нить (30.3.1.3, 30.3.1.4) или- когда вызов функции
wait()
,wait_until()
илиwait_for()
в переменной условия (30.5.1, 30.5.2) не отвечает Постусловие. -end note]В таких случаях
std::terminate()
называется (18.8.3). В ситуации где встречный обработчик не найден, он определяется реализацией независимо от того, разорван ли стек до того, какstd::terminate()
. В ситуации, когда поиск обработчика (15.3) встречает внешний блок функции с помощью noexcept-specification, которая не допускает исключение (15.4), определяется реализацией, будет ли стека разматываться, разматываться частично или вообще не разматываться до вызоваstd::terminate()
. Во всех других ситуациях стек не должен разматываться доstd::terminate()
. Реализация не допускается преждевременно прекращается, основываясь на процесс размотки вызовет вызовstd::terminate()
.