13

专注于 Visual C++,您是否体验过使用throw()(即__declspec(nothrow))非抛出规范在 C++ 代码中的显着性能提升?它真的对优化器有帮助吗?是否有任何基准显示性能提升?

我在互联网上发现了不同的(相反的)建议:

Boost exception-specification 的基本原理反对 的,相反,Larry Osterman在他的博客文章中throw()似乎支持它: Why add a throw() to your methods?

(我想澄清一下,我对 VC++ 特定代码感兴趣;我知道在 GCC 中,throw()由于运行时检查,规范实际上可能是“悲观化”。)

PS阅读 ATL 标头,我发现它throw()被普遍使用;此外,我在这篇 MSDN 文章中发现了一个方便的 C++ RAIIunique_handle类,它也使用了规范。throw()

4

3 回答 3

4

MSVC 编译器将其视为优化提示,是的。

Boost 必须是跨平台的,它们必须在各种编译器上寻找安全且高效的东西。正如 boost 文档所说,某些编译器在指定时可能会生成较慢的代码throw(),并且在许多情况下,编译器可以推断出无论是否有throw()规范都不会引发异常,因此对于 Boost,最安全的方法是永远不要使用投掷规格。

但是,如果您专门针对 MSVC,则throw()有效地告诉编译器不要为函数生成异常处理代码,这可能会在函数过于复杂而编译器无法确定不会抛出异常的情况下加快速度。

于 2012-05-12T09:49:38.130 回答
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
};
于 2012-05-12T08:08:44.430 回答
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 所说

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

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

EDIT2 实际上,Microsoft 违反了标准行为并且不会为throw(). 那么,你可以使用它throw()来提高性能。

于 2012-05-12T10:26:23.667 回答