2 - C++标准异常与noexcept
本文将简要介绍C++的标准异常层次结构,以及noexcept
关键字。
标准异常层次结构
C++标准库中抛出的异常都是std::exception
为基类的类对象,如图:
利用多态性捕获异常
当使用多条catch
子句捕获多种异常时,要捕获的异常应 按子类 -> 基类的顺序出现。例如以下两种写法会带来截然不同的结果:
// 写法1
try
{
// ...
}
catch (const invalid_argument& e)
{
// A
}
catch (const exception& e)
{
// B
}
// 写法2
try
{
// ...
}
catch (const exception& e)
{
// B
}
catch (const invalid_argument& e)
{
// A
}
写法1是正确的,如果捕获了invalid_argument
异常,就会执行A;而写法2是错误的,不论捕获什么异常,总会执行B。
noexcept关键字
可以用noexcept
标记函数,指出它不抛出任何异常:
void printVal(const vector<int>& values) noexcept;
如果一个函数带有noexcept
标记,却以某种方式抛出了异常,C++将调用terminate()
来终止程序运行。
还能把noexcept
作为运算符使用,格式为noexcept(expression)
。有两种用法:
- 如果表达式为true,则指定被标记的函数不抛出异常(也就是上边的
noexcept
其实是noexcept(true)
);如果表达式为false,则被标记的函数可以抛出任何异常。 - 如果表达式被标记为
noexcept
,会返回true,看看下边的例子:
void f1() noexcept {};
void f2() noexcept(false) {};
void f3() noexcept(noexcept (f1())) {}
void f4() noexcept(noexcept (f2())) {}
int main()
{
cout << noexcept(f1()) << noexcept(f2()) << noexcept(f3()) << noexcept(f4());
}
输出1010:
noexcept(f1())
为true:因为f1()被noexcept
显式标记。noexcept(f2())
为false:因为f2()被noexcept(false)
标记。noexcept(f3())
为true:因为noexcept(f1())
是true。noexcept(f4())
为false:因为noexcept(f2())
是false。
参考资料
- 飘零的落花 - 现代C++详解
- C++20高级编程