前言
noexcept
关键字是仅用于C++的异常处理关键字。
在上一篇中,我们认识了异常的抛出、捕捉及重载。不妨想想以下问题:
- 如果有一个函数(可能来自第三方库)会抛出异常,怎么知道它可能抛出的类型呢?
查看源代码确实是一种方式,但如果函数体很长,或函数嵌套函数呢?
如果第三方库函数只有函数声明,没有函数实现呢?
这就来到了今天的主题——异常规格说明符
何为异常规格说明?
异常规格说明,是用于说明函数可能抛出的异常种类,作为函数声明的修饰符,跟在参数列表【()
】后面,与静态函数说明const
1放在一起。
语法
它的标准语法为:
[adding] ret-type func-name( list ) [adding] throw( exception ) ;
其中,throw()
前是一般的函数声明(或实现),throw
里写数据类型,表示函数可能抛出的异常,如:
void func1() throw(); //表示不抛出任何异常
void func2() throw(int); //可能抛出int型异常
void func3() throw(const char * , float); //可能抛出C风字符串和单精浮点型异常
void func4() throw(thread); //可能抛出thread对象异常
可以看出,throw()
里不写任何类型表示该函数不抛出任何异常。
意义
- 有了异常规格说明,当需要了解函数异常时,只需打开声明就一目了然了。
- 维护者不应抛出任何说明符之外的异常类型。
- 说明符是函数接口的一部分,用于说明函数如何正确使用。
规格说明之外的异常
考虑以下代码:
void func() throw(int){
throw 'x';//与异常规格说明不符
}
int main(){
try{
func();
}
catch(int e){
cout<<"exception in int!\n";
}
catch(char e){
cout<<"exception in char!\n";
}
return 0;
}
编译器会作何反应?下面罗列了不符编译器的反应。
- BCC:
Abnormal program termination
- g++:
terminate called after throwing an instance of 'char'
- VS2019、VC:
exception in char!
- 多数线上编译器:
warning: dynamic exception specifications are deprecated in C++11 [-Wdeprecated] 3 | void func() throw(int) | ^~~~~ terminate called after throwing an instance of 'char' Aborted (core dumped)
可以看到,除了VS、VC,大部分编译器会直接拒绝非规格说明的异常抛出。因为这是C++11
规范。
noexcept关键字
注:
noexcept
关键字仅可用于C++。
该关键字于C++11加入,用于替代throw()
说明符。表示函数不会抛出任何异常。
它的标准形式为:
ret-type func_name( [params] ) [adding...] noexcept( noexcept(exception) )
第一个noexcept后的()
中是一个布尔表达式,表示当且仅当布尔值为真时该函数是noexcept
的(即它是throw()
的)。
第一个noexcept
后的(...)
可以省略,相当于noexcept(true)
。(表示任何时候都不会抛出异常)
第二个noexcept(…)类似于一个函数,其参数必须为函数执行语句(带括号,形如func()
),表示检查该该函数是否抛出异常。
以下函数声明表示当且仅当funcc()
不抛出异常时func()
也不抛出异常2:
void func() noexcept( noexcept(funcc()) );
异常的传递性
使用除VC、VS以外的编译器执行以下程序(因为VC、VS不遵守C++11异常规范):
#include<iostream>
using namespace std;
void funcc(){
throw 114514;
}
void func() noexcept//不会抛出异常
{
funcc();//在另一个函数中抛出异常
}
int main(){
try{
func();
}
catch(int err){
cerr<<"exception!\n";
}
return 0;
}
terminate called after throwing an instance of 'int'
Aborted (core dumped)
不难看出,异常是传递的,一个函数是noexcept的,当且仅当它的函数主体、所调用的函数、方法都不抛出异常。即使是在调用的函数中抛出异常,也不是noexcept。
将以上程序改为:
#include<iostream>
using namespace std;
void funcc(){
throw 114514;
}
void func()
/* [-] *///noexcept
/* [+] */ noexcept( noexcept(funcc()) )
{
funcc();
}
int main(){
try{
func();
}
catch(int err){
cerr<<"exception!\n";
}
return 0;
}
#(正常运行)
exception!
@HaohaoCppDebuger|寻兰
2021/12/21
THANK YOU !