Разница между C++03 throw() спецификатором C++11 не исключая
Есть ли другая разница между throw()
а также noexcept
кроме проверки времени выполнения и времени компиляции соответственно?
Статья Википедии C++11 предполагает, что спецификаторы бросков C++03 устарели.
Почему так noexcept
достаточно ли, чтобы покрыть все это во время компиляции?
[Примечание: я отослал этот вопрос и эту статью, но не смог получить вескую причину устаревания.]
3 ответа
Спецификаторы исключений устарели, потому что спецификаторы исключений, как правило, ужасная идея. noexcept
был добавлен, потому что это единственно разумное использование спецификатора исключения: знать, когда функция не будет генерировать исключение. Таким образом, это становится бинарным выбором: функции, которые будут выбрасывать, и функции, которые не будут выбрасывать.
noexcept
был добавлен, а не просто удалить все спецификаторы броска, кроме throw()
так как noexcept
более мощный. noexcept
может иметь параметр, который компилируется во время компиляции. Если логическое значение истинно, то noexcept
палочки. Если логическое значение ложно, то 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
или же throw()
попытки выбросить исключение, единственное отличие состоит в том, что один вызывает terminate
и другие звонки unexpected
и последний стиль обработки исключений фактически устарел.
std:: surprise () вызывается средой выполнения C++, когда нарушается спецификация динамического исключения: исключение выдается из функции, спецификация исключения которой запрещает исключения этого типа.
std:: непредвиденный () также может быть вызван непосредственно из программы.
В любом случае, std:: непредвиденный вызов вызывает установленный в данный момент std:: surprise_handler. Стандартный std::ести_handler вызывает std::terminate.