如果一个 try-catch 块被证明是非抛出的,编译器必须总是删除它
Must a compiler always remove a try-catch block if it's proven to be non-throwing
考虑一下:
#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_personality
和 Call 1
的任何异常处理代码。
使用不同的编译器时可以依赖这样的优化吗?我只考虑C++11
及以上
noexcept
说明符被添加到 c++11 作为 throw()
的替代。它保证函数不会抛出。它与 throw()
的区别在于,对于 noexcept
,如果函数 实际上抛出 ,则堆栈 仅可能被展开 ,前者不是这种情况(堆栈总是展开)。这样可以实现更多优化,例如完全省略异常处理。
总而言之,由编译器决定是否省略异常处理,但是对于 noexcept
它没有理由不这样做,这确实其他情况下很难确定。
考虑一下:
#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_personality
和 Call 1
的任何异常处理代码。
使用不同的编译器时可以依赖这样的优化吗?我只考虑C++11
及以上
noexcept
说明符被添加到 c++11 作为 throw()
的替代。它保证函数不会抛出。它与 throw()
的区别在于,对于 noexcept
,如果函数 实际上抛出 ,则堆栈 仅可能被展开 ,前者不是这种情况(堆栈总是展开)。这样可以实现更多优化,例如完全省略异常处理。
总而言之,由编译器决定是否省略异常处理,但是对于 noexcept
它没有理由不这样做,这确实其他情况下很难确定。