【问题标题】:Must a compiler always remove a try-catch block if it's proven to be non-throwing如果一个 try-catch 块被证明是不抛出的,编译器必须总是删除它
【发布时间】:2026-02-23 22:25:01
【问题描述】:

考虑一下:

#include <stdexcept>

template <class T>
void F(T &&t) {
    try {
        t(); 
    } catch(...) {}
}

int main() {
    F([]() noexcept {});             // Call 1
    F([]{});                         // Call 2
    F([]{ throw std::exception{}; });// Call 3
}

我在clang++-6.0 上发现带有标志-std=c++17,无论我给出的优化标志如何,始终没有__gxx_personalityCall 1 的任何异常处理代码。

在使用不同的编译器时可以依赖这种优化吗?我只考虑C++11及以上。

【问题讨论】:

  • @Fureeish 你能回答一下吗?
  • 完成。请看下面的答案
  • @Fureeish 谢谢,终于明白noexcept了。
  • @JiaHaoXu:我感觉题主和正文有细微差别。 “可以依赖这样的(a)优化吗?”暗示标题应该是“必须编译器总是删除一个 try-catch 块,如果它被证明是不抛出?”
  • @MSalters 标题已澄清,谢谢指出。

标签: c++ c++11 optimization exception-handling try-catch


【解决方案1】:

noexcept 说明符已添加到 c++11 以替代 throw()。它保证函数不会抛出。它与throw() 的区别在于,在noexcept 中,如果函数实际抛出,堆栈可能只会展开,而前者并非如此一个(堆栈总是展开)。这可以实现更多优化,例如完全省略异常处理。

总而言之,当它决定省略异常处理时,取决于编译器,但对于noexcept,它没有理由不这样做,这在其他情况下真的很难确定。

【讨论】: