首页 > 解决方案 > Must a compiler always remove a try-catch block if it's proven to be non-throwing

问题描述

Consider this:

#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
}

I found on clang++-6.0 with flags -std=c++17, regardless of the optimization flags I gave, there is always no __gxx_personality and any exception handling code for Call 1.

Can such optimization be relied on when using a different compiler? I only consider C++11 and above.

标签: c++c++11optimizationexception-handlingtry-catch

解决方案


noexcept specifier was added to c++11 as a replacement for throw(). It guarantees that the function will not throw. The difference between it and throw() is that with noexcept, if the function actually throws, the stack only maybe gets unwinded, which was not the case with the former one (stack always gets unwinded). This enables more optimizations, such as completely omitting the exception handling.

To summarize, it's up to compiler when it decides to omit the exception handling, but with noexcept it has no reason to not do so, which was really hard to determinate in other case.


推荐阅读