在 C++ 中什么可以(什么不能)抛出异常?

Dmi*_*y J 5 c++ exception

是否存在可能导致 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()它是无异常的?

Seb*_*edl 2

是的,C++ 中可以抛出的事物列表可以被详尽地定义。

  • throw表达
  • new可以扔bad_alloc
  • dynamic_cast可以扔bad_cast
  • typeid可以扔bad_typeid
  • noexcept对不是或的函数的任何调用throw()

最后一点也适用于 C++ 的所有隐式函数调用:默认/复制/移动构造函数、重载运算符、析构函数(请注意,这些默认为noexcept)和转换运算符。

如果您对特定表达式有疑问,可以使用noexcept运算符让编译器告诉您该表达式理论上是否可能抛出异常。