例外状况是 C++ 语言功能,程式设计人员对于可由函式传之例外状况类型的意图。
?
酷游专员??搜KUK3219原创提供:您可以使用 例外状况规格来指定函式可能会或可能不会结束例外状况。编译器可以使用这项资讯来优化对函式的呼叫,并在非预期的例外状况逸出函式时终止程式。
在 C++17 之前,有两种例外状况规格。 noexcept 规格是 C++11 中的新功能。它会指定是否可以逸出函式的潜在例外状况集合是空的。动态例外状况规格或 throw(optional_type_list) 规格在 C++11 中已被取代,并在 C++17 中移除,但 除外 throw() ,这是 的 noexcept(true) 别名。此例外状况规格的设计目的是提供哪些例外状况可能会掷出函式的摘要资讯,但实际上发现有问题。一个证明有点有用的动态例外状况规格是无条件 throw() 规格。例如,函式宣告:
通知编译器,函式不会回报任何例外状况。不过,在模式中 /std:c++14 ,如果函式回报例外状况,可能会导致未定义的行为。因此,我们建议使用 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 模式中,、 noexceptnoexcept(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 掷回例外状况,而且可能会在 、 /EHa 或 /EHac 底下 /EHs 结构化例外状况。
下表摘要说明 C++ 函式是否可能会在各种编译器例外状况处理选项
没有例外状况规格的 C++ 函式 :/EHsc??是 ?/EHs??是 ?/EHa?是 ?/EHac 是
具有 noexcept 、 noexcept(true) 或 例外状况规格的 throw() C++ 函式:
/EHsc?否 ?/EHs??否 ?/EHa?是 ?/EHac 是
具有 noexcept(false) 、 throw(...) 或 例外状况规格的 throw(type) C++ 函式 :
/EHsc?是 ?/EHs??是 ?/EHa?是 ?/EHac 是
范例
// 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
|