Спецификации исключений (throw, noexcept) (C++)
Спецификации исключений — это функция языка C++, указывающая намерение программиста о типах исключений, которые могут распространяться функцией. Можно указать, что функция может или не выйти из исключения с помощью спецификации исключения. Компилятор может использовать эти сведения для оптимизации вызовов функции и завершения программы, если непредвиденное исключение выходит из функции.
До C++17 существовали два типа спецификации исключений. Спецификация noexcept была новой в C++11. Он указывает, является ли набор потенциальных исключений, которые могут экранировать функцию, пуста. Спецификация динамического исключения или throw(optional_type_list)
спецификация устарела в C++11 и удалена в C++17, за исключением throw()
псевдонима noexcept(true)
. Эта спецификация исключений была разработана для предоставления сводных сведений о том, какие исключения могут быть выброшены из функции, но на практике было обнаружено, что это проблематично. Одна спецификация динамического исключения, которая оказалась несколько полезной, была безусловной throw()
спецификацией. Например, объявление функции:
void MyFunction(int i) throw();
сообщает компилятору, что функция не создает исключений. Однако в /std:c++14
режиме это может привести к неопределенному поведению, если функция создает исключение. Поэтому рекомендуется использовать noexcept
оператор вместо приведенного выше:
void MyFunction(int i) noexcept;
В следующей таблице приведены сведения о реализации спецификаций исключений Microsoft C++:
Спецификация исключений | Значение |
---|---|
noexcept noexcept(true) throw() |
Функция не вызывает исключений. В /std:c++14 режиме (по умолчанию) noexcept и noexcept(true) эквивалентны. При возникновении исключения из функции, объявленной noexcept или noexcept(true) std::terminate вызываемой. Если исключение создается из функции, объявленной как throw() в /std:c++14 режиме, результат не определен. Не вызывается определенная функция. Это расхождение со стандартом C++14, которое требуется компилятору для вызова std::unexpected . Visual Studio 2017 версии 15.5 и более поздних версий: в /std:c++17 режиме , noexcept noexcept(true) и throw() все эквивалентны. В /std:c++17 режиме throw() является псевдонимом для noexcept(true) . В /std:c++17 режиме и более поздних версиях, когда исключение создается из функции, объявленной с любой из этих спецификаций, std::terminate вызывается в соответствии со стандартом C++17. |
noexcept(false) throw(...) Нет спецификации |
Функция может вызывать исключение любого типа. |
throw(type) |
(C++14 и более ранних версий) Функция может вызывать исключение типа type . Компилятор принимает синтаксис, но интерпретирует его как noexcept(false) . В /std:c++17 режиме и более поздних версиях компилятор выдает предупреждение C5040. |
Если обработка исключений используется в приложении, в стеке вызовов должна быть функция, которая обрабатывает исключения, прежде чем они выходят из внешней область функции, помеченной noexcept
или noexcept(true)
throw()
. Если какие-либо функции, вызываемые между тем, который вызывает исключение, и тот, который обрабатывает исключение, указывается как noexcept
noexcept(true)
(или throw()
в /std:c++17
режиме), программа завершается, когда функция noexcept распространяет исключение.
Поведение исключения функции зависит от следующих факторов:
Какой языковой стандартный режим компиляции задан.
В какой среде выполняется компиляция функции — в C или C++.
Какой
/EH
параметр компилятора вы используете.Задана ли явно спецификация исключений.
Явные спецификации исключений не разрешено использовать для функций C. Предполагается, что функция C не создает исключения под , и может вызывать структурированные /EHsc
исключения в /EHs
, /EHa
или /EHac
.
В следующей таблице приводится сводка о том, может ли функция C++ потенциально вызывать различные параметры обработки исключений компилятора:
Функция | /EHsc |
/EHs |
/EHa |
/EHac |
---|---|---|---|---|
Функция C++ без спецификации исключений | Да | Да | Да | Да |
Функция C++ с noexcept спецификацией исключений noexcept(true) , или throw() спецификацией исключений |
No | No | Да | Да |
Функция C++ с noexcept(false) спецификацией исключений throw(...) , или throw(type) спецификацией исключений |
Да | Да | Да | Да |
Пример
// exception_specification.cpp
// compile with: /EHs
#include <stdio.h>
void handler() {
printf_s("in handler\n");
}
void f1(void) throw(int) {
printf_s("About to throw 1\n");
if (1)
throw 1;
}
void f5(void) throw() {
try {
f1();
}
catch(...) {
handler();
}
}
// invalid, doesn't handle the int exception thrown from f1()
// void f3(void) throw() {
// f1();
// }
void __declspec(nothrow) f2(void) {
try {
f1();
}
catch(int) {
handler();
}
}
// only valid if compiled without /EHc
// /EHc means assume extern "C" functions don't throw exceptions
extern "C" void f4(void);
void f4(void) {
f1();
}
int main() {
f2();
try {
f4();
}
catch(...) {
printf_s("Caught exception from f4\n");
}
f5();
}
About to throw 1
in handler
About to throw 1
Caught exception from f4
About to throw 1
in handler
См. также
try
, throw
и catch
операторы (C++)
Современные рекомендации по C++ по исключению и обработке ошибок
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по