C++:可以"尝试{foo();} catch(...){throw;}"优化为"foo();"?

Phi*_*ßen 6 c++ exception-handling compiler-optimization

在C++中,是以下代码

try {
  foo();
} catch (...) {
  throw;
}
Run Code Online (Sandbox Code Playgroud)

在语义上只是foo像这样调用?

foo();
Run Code Online (Sandbox Code Playgroud)

如果是这样,我是否可以期待最先进的编译器避免第一个版本到第二个版本(在启用优化的情况下进行编译时)?

换句话说,如果我编译此代码NDEBUG并启用优化

try {
  foo();
} catch (...) {
  assert(some_check());
  throw;
}
Run Code Online (Sandbox Code Playgroud)

我可以假设这个丑陋的版本永远不会慢

#ifndef NDEBUG
  try {
#endif
    foo();
#ifndef NDEBUG
  } catch (...) {
    assert(some_check());
    throw;
  }
#endif
Run Code Online (Sandbox Code Playgroud)

小智 3

不,两者并不等同。

当没有异常处理程序时堆栈是否展开是实现定义的([except.handle]p9)。当处理程序存在但它只是重新引发异常时,必须至少展开堆栈直到重新引发异常的点。

那是:

struct S { ~S(); };
void foo() { S s; throw 0; }
int main() {
  try { foo(); }
  catch(...) { throw; }
}
Run Code Online (Sandbox Code Playgroud)

这必须调用 的s析构函数。当try { ... } catch (...) { throw; }被删除时,不再需要调用 的s析构函数。

甚至有可能,根据s析构函数的作用,执行永远不会达到异常的重新抛出,通过添加例如:

#include <stdlib.h>
S::~S() { exit(0); }
Run Code Online (Sandbox Code Playgroud)

现在,程序必须成功运行,但是当try { ... } catch (...) { throw; }删除它时,就不再需要了,并且在真实系统上可能并且确实会发生崩溃。