专注于Visual C ++,您是否曾使用throw()
(即__declspec(nothrow)
)非投掷规范在C ++代码中获得显着的性能提升?
它真的有助于优化器吗?
是否有任何基准显示性能提升?
我在互联网上找到了不同的(相反的)建议:
Boost exception-specification rationale 反对 throw()
,而Larry Osterman似乎在他的博文中赞成:Why add a throw() to your methods?
(我想澄清我对VC ++特定代码感兴趣;我知道在GCC中throw()
规范实际上可能是一个“悲观化”,因为运行 - 时间检查。)
P.S。读取ATL标题,我发现普遍使用throw()
;此外,我在this MSDN article中找到了一个方便的C ++ RAII unique_handle
类,它也使用了throw()
规范。
答案 0 :(得分:4)
MSVC编译器将其视为优化提示,是的。
Boost必须是跨平台的,他们必须在各种编译器上寻找安全有效的东西。正如提升文档所说,某些编译器在指定throw()
时可能会生成较慢的代码,并且在许多情况下,编译器可以推断出没有抛出任何异常,无论是否存在throw()
规范,因此对于Boost,最安全的方法是永远不要使用throw-specifications。
但是,如果您专门针对MSVC,那么throw()
会有效地告诉编译器不要为该函数生成异常处理代码,这可能会在函数对于编译器来说过于复杂的情况下提高速度。确定不会抛出任何异常。
答案 1 :(得分:1)
我添加它,但它不是为了帮助优化器帮助我编写更正确的代码。
class X
{
public:
void swap(X& rhs) throw(); // Swap better not ever throw
// If it does there is something else
// much more seriously wrong
};
答案 2 :(得分:1)
throw()
的主要问题是标记为throw()
的函数内的代码可以抛出。
例如,这将完美地运作:
void foo() throw()
{
throw "haha\n";
}
int main()
{
try {
foo();
}
catch(const char* s) {
std::cout << s;
}
return 0;
}
注意,foo不会throw
到main
。并且您不会捕获异常(就像您评论throw()
说明符一样)。相反,编译器将使用try{}catch()
块包装代码函数。生成异常时,它将由全局处理程序处理(这意味着您的程序默认崩溃)。
注意,编译器必须用try{}cath()
块包装函数代码,除非编译器确定,内部代码不可能生成异常。
因此,可以使用foo
的调用者进行一些优化,但 foo
内的事情变得更加复杂。
修改强>
与__declspec(nothrow)
不同的是:Microsft tells,
该属性告诉编译器声明的函数和 它调用的函数永远不会抛出异常。
这意味着,编译器可以省略try{}catch()
包装器代码。
<强> EDIT2 强>
实际上,Microsoft违反了标准行为,并且没有为throw()
生成warpper。那么,您可以使用throw()
来提高效果。