是否存在可能导致 C++ 异常的“代码语句”的完整列表(可能是递归定义的)?像这样的东西:
1)throw
声明(自然)
2) 调用new
3) 调用标准库中记录为能够抛出异常的任何函数。
4) 调用包含 1-3 操作的任何用户定义函数(包括构造函数)。
5)还有别的事吗?在堆栈上分配本地对象、对内置类型的操作、取消引用指针、类型转换 - 它们能够抛出异常吗?
6) 其他一切均无异常。
我所说的无异常并不是指总是成功的操作。取消引用指针肯定不是。但将其包装在块中仍然没有意义try-catch
,考虑函数取消引用指针的异常安全性等。因此,成功或导致未定义行为的代码可以被视为无异常。
更新。尽管我写了最后一段,但我仍然得到了一条评论,即未定义的行为也可能抛出,所以让我解释一下我的意思。考虑以下代码:
void bar();
Class C{
...
public:
foo() {
something_that_breaks_class_invariants;
bar();
something_that_restores_class_invariants;
}
}
Run Code Online (Sandbox Code Playgroud)
如果我正确理解异常安全是什么,那么如果bar()
可以抛出异常,那么这段代码就很糟糕。我应该改变语句的顺序,或者我应该包装bar()
在try-catch
块中,恢复类不变量并进一步传播异常。
但是,如果 bar() 成功返回或导致未定义的行为(因为,我不知道,其他东西被破坏了),那么就foo()
可以了。foo()
不能做任何事情,也不应该关心 可能的未定义行为bar()
。从这个意义上讲bar()
是无异常的,可以标记的noexcept
,等等。
所以我的问题是:什么样的语句可以认为bar()
它是无异常的?
是的,C++ 中可以抛出的事物列表可以被详尽地定义。
throw
表达new
可以扔bad_alloc
dynamic_cast
可以扔bad_cast
typeid
可以扔bad_typeid
noexcept
对不是或的函数的任何调用throw()
最后一点也适用于 C++ 的所有隐式函数调用:默认/复制/移动构造函数、重载运算符、析构函数(请注意,这些默认为noexcept
)和转换运算符。
如果您对特定表达式有疑问,可以使用noexcept
运算符让编译器告诉您该表达式理论上是否可能抛出异常。