Спецификаторы исключений устарели, потому что спецификаторы исключений, как правило, ужасная идея . noexcept
был добавлен, потому что это единственное разумно полезное использование спецификатора исключения: знание того, когда функция не генерирует исключение. Таким образом, это становится двоичным выбором: функции, которые будут вызывать и функции, которые не будут выбрасывать.
noexcept
был добавлен вместо того, чтобы просто удалить все спецификаторы выброса, кроме того, throw()
что noexcept
он более мощный. noexcept
может иметь параметр, который во время компиляции преобразуется в логическое значение. Если логическое значение истинно, то noexcept
прилипает. Если логическое значение false, то noexcept
функция не прилипает и функция может выбросить.
Таким образом, вы можете сделать что-то вроде этого:
struct<typename T>
{
void CreateOtherClass() { T t{}; }
};
Выбрасывает CreateOtherClass
исключения? Может, если T
конструктор по умолчанию может. Как мы узнаем? Как это:
struct<typename T>
{
void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; }
};
Таким образом, CreateOtherClass()
будет сгенерировано, если конструктор по умолчанию данного типа выбрасывает. Это устраняет одну из основных проблем со спецификаторами исключений: их неспособность распространяться вверх по стеку вызовов.
Вы не можете этого сделать с throw()
.
noexcept
может потребоваться проверка во время выполнения. Основное различие между ними в том , что ломаяnoexcept
причиныstd::terminate
, разбиваяthrow
причиныstd::unexpected
. Также в этих случаях немного другое поведение при раскручивании стека.