throw()(即__declspec(nothrow))是否在Visual C ++中带来了实实在在的好处?

时间:2012-05-11 22:50:31

标签: c++ visual-c++ exception

专注于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()规范。

3 个答案:

答案 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不会throwmain。并且您不会捕获异常(就像您评论throw()说明符一样)。相反,编译器将使用try{}catch()块包装代码函数。生成异常时,它将由全局处理程序处理(这意味着您的程序默认崩溃)。

注意,编译器必须try{}cath()块包装函数代码,除非编译器确定,内部代码不可能生成异常。

因此,可以使用foo调用者进行一些优化,但 foo内的事情变得更加复杂。

修改

__declspec(nothrow)不同的是:Microsft tells

  

该属性告诉编译器声明的函数和   它调用的函数永远不会抛出异常。

这意味着,编译器可以省略try{}catch()包装器代码。

<强> EDIT2 实际上,Microsoft违反了标准行为,并且没有为throw()生成warpper。那么,您可以使用throw()来提高效果。