编译器是否必须始终删除 try-catch 块(如果它被证明是非抛出的)

Must a compiler always remove a try-catch block if it's proven to be non-throwing

本文关键字:证明是 证明 是非 如果 是否 try-catch 删除 编译器      更新时间:2023-10-16

考虑一下:

#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,无论我给出的优化标志如何,Call 1始终没有__gxx_personality和任何异常处理代码。

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

noexcept说明符被添加到 C++11 中,作为throw()的替代品。它保证函数不会抛出。它和throw()之间的区别在于,对于noexcept,如果函数实际抛出,堆栈只会被展开,而前者则不是这种情况(堆栈总是被展开(。这样可以进行更多优化,例如完全省略异常处理。

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