Леонид Asked:2024-04-18 22:06:35 +0000 UTC2024-04-18 22:06:35 +0000 UTC 2024-04-18 22:06:35 +0000 UTC 向每个函数/方法添加 noexcept 是否有意义? 772 我注意到函数很少被标记为noexcept不抛出或处理异常。虽然,在我看来,我们应该帮助编译器并明确指示该函数将是noexcept,即使该函数并不大,并且它本身可以这样标记它。将所有函数声明为 是否有意义noexcept?这将如何影响性能? c++ 1 个回答 Voted Best Answer Halturin Evgeniy 2024-04-19T20:52:39Z2024-04-19T20:52:39Z https://stackoverflow.com/questions/16104057/does-no except- improve-performance 就我个人而言,我最反对 Steve Jessop 的回答。稍微解释一下,我会说: 不管怎样,现代编译器noexcept生成的代码都是经过优化的,就好像它不会抛出任何异常一样。如果发生异常,它会使用特定的代码对其进行处理(从目标性能的角度来看可能不是最佳的),该代码已经考虑了引发异常的代码是否被标记noexcept。 这是各种淫秽内容的示例 #include <iostream> #include <vector> #include <exception> /* template <typename ...types> inline void noopt(types ...args) { __asm { DONOTHING: } } */ const int LACK = rand(); template<bool B> struct noexcept_BOOL { noexcept_BOOL() noexcept(B) { //if (!B and LACK > 1000000000) throw std::exception("AHAHA"); }; noexcept_BOOL(const noexcept_BOOL& other) noexcept(B) = default; noexcept_BOOL(noexcept_BOOL&& other) noexcept(B) = default; noexcept_BOOL& operator= (const noexcept_BOOL& other) noexcept(B) = default; noexcept_BOOL& operator= (noexcept_BOOL&& other) noexcept(B) = default; }; template<typename T> __declspec(noinline) void foo(size_t N, size_t C) { for (size_t c = 0; c < C; ++c) { std::vector<T> vec1(N); std::vector<T> vec2; for (size_t i = 0; i < N; ++i) { vec2.emplace_back(); //noopt(i); } for (size_t i = 0; i < N; ++i) { std::swap(vec1[i], vec2[i]); //noopt(i); } vec1.swap(vec2); for (size_t i = 0; i < N; ++i) { vec1.erase(vec1.begin()); //noopt(i); } //noopt(j); } } int main() { auto N = (rand() % 2 + 1) * 10000; auto C = (rand() % 2 + 1) * 100; try { auto begin = clock(); foo<noexcept_BOOL<true>>(N, C); auto end = clock(); std::cout << "noexcept(true) - " << end - begin << "ms" << std::endl; } catch (...) { return 666; } try { auto begin = clock(); foo<noexcept_BOOL<false>>(N, C); auto end = clock(); std::cout << "noexcept(false) - " << end - begin << "ms" << std::endl; } catch (...) { return 1; } std::cout << "\n\npress [Enter]..."; std::cin.get(); } 它们的测量结果是相同的。这也不足为奇。这两种情况的汇编器就像豆荚里的两颗豌豆,即使在调试版本上也是如此。那些。事实上,所使用的标准库方法的行为不以任何方式使用有关标签的信息noexcept(除了它将自己的方法标记为noexcept依赖于模板参数这一事实)。是的,当然,如果您尝试,您可以编写肯定会依赖于noexcept. 但这并不容易做到。只要看看 Releas 编译器做了什么就可以了。 foo<noexcept_BOOL<false>>(N, C); ... ... 00007FF7074211FD call foo<noexcept_BOOL<0> > (07FF707421350h) 到目前为止,一切都很好。false- 这0。进而? foo<noexcept_BOOL<true>>(N, C); ... ... 00007FF707421257 call foo<noexcept_BOOL<0> > (07FF707421350h) !!!我们明确指出传递的类型是noexcept_BOOL<true>。但它再次foo使用参数调用noexcept_BOOL<0>。他只是不在乎noexcept。对他来说,这些是完全相同的类型。但如果抛出异常,情况就会发生一点变化。但并不多。恰好是最低限度需要的数量。 总的来说,我现在已经从“noexcept除非错误才写”规则转变为“noexcept只在必要时写”规则。 (当确切地说这是必要的时,我简单地确定。如果我不知道某件事是必要的,但它不是必要的。如果我知道为什么它是必要的,那么它绝对是必要的)))编译器比99.99%的程序员。这是事实 补充 如果我们谈论更具体的实用建议,我们可以给出以下内容: 如果您确定您的类不能具有不一致的状态,那么noexcept您可以标记可能涉及“重”算法的方法。
https://stackoverflow.com/questions/16104057/does-no except- improve-performance 就我个人而言,我最反对 Steve Jessop 的回答。稍微解释一下,我会说:
这是各种淫秽内容的示例
它们的测量结果是相同的。这也不足为奇。这两种情况的汇编器就像豆荚里的两颗豌豆,即使在调试版本上也是如此。那些。事实上,所使用的标准库方法的行为不以任何方式使用有关标签的信息
noexcept(除了它将自己的方法标记为noexcept依赖于模板参数这一事实)。是的,当然,如果您尝试,您可以编写肯定会依赖于noexcept. 但这并不容易做到。只要看看 Releas 编译器做了什么就可以了。到目前为止,一切都很好。
false- 这0。进而?!!!我们明确指出传递的类型是
noexcept_BOOL<true>。但它再次foo使用参数调用noexcept_BOOL<0>。他只是不在乎noexcept。对他来说,这些是完全相同的类型。但如果抛出异常,情况就会发生一点变化。但并不多。恰好是最低限度需要的数量。总的来说,我现在已经从“
noexcept除非错误才写”规则转变为“noexcept只在必要时写”规则。(当确切地说这是必要的时,我简单地确定。如果我不知道某件事是必要的,但它不是必要的。如果我知道为什么它是必要的,那么它绝对是必要的)))编译器比99.99%的程序员。这是事实
补充 如果我们谈论更具体的实用建议,我们可以给出以下内容:
如果您确定您的类不能具有不一致的状态,那么
noexcept您可以标记可能涉及“重”算法的方法。