4

我开始添加noexcept到我的代码中,但我想知道是否将其添加到内联函数中是否明智。我假设优化器在明显不需要时会省略运行时检查......但从人类/风格的角度来看,是否值得将 noexcept 添加到 getter、设置、增量函数等琐碎的函数中?我认为这是完全明显的视觉混乱。我正在讨论一个规则,即内联函数可以省略 noexcept,但是如果它们不抛出,普通的 .hpp/.cpp 函数必须有它。

其次,我有大量根本无法抛出的代码,因为它没有分配(在我的国际象棋引擎中),不包括 STL 或其他任何可能失败的东西,所以总是可以保证成功。noexcept 不会因为运行时检查而减慢它的速度吗?有没有人使用宏在使用构建之间切换noexceptDEBUG但切换到throw()发布,这只是编译时的?

4

2 回答 2

4

如果您的内联函数是叶级函数,即它本身不调用任何函数,那么理论上编译器可以确定它不会抛出并忽略任何可能生成的异常处理。所以在性能方面,它可能被证明是不必要的。

话虽如此,您不应该期望看到添加noexcept. 为处理异常传播而必须生成的任何代码都不应该通过添加noexcept. 值得注意的是,如果 noexcept 函数抛出异常,则允许编译器完全省略展开堆栈。这在很大程度上是直接好处的noexcept来源。

至于风格推荐,首先要考虑是否noexcept会成为您界面的有用部分。诸如移动操作之类的事情可以从算法的原因中受益匪浅noexcept,但除此之外,真正由您来决定哪些地方noexcept对您、您的界面和界面的用户有价值。

如果这不能回答您的问题,请随时评论我的答案,我会进一步澄清。

旁注:throw(),以及在 C++11 中被弃用的,不提供与 . 相同的保证noexcept。如果通过声明的函数抛出异常throw(),则堆栈必须完全展开到该函数的调用者。有关此行为的参考,请参阅 C++ 标准版本 N3337 中的 15.5.2.1。

于 2015-08-05T08:48:33.727 回答
0

通过向函数添加 noexcept 或 noexcept(true) 说明符,您要求编译器添加运行时检查并调用 std::terminate。所以你有一个小的性能影响。你应该从中有所收获,否则我看不到任何意义。标准库具有以下特点:

is_nothrow_constructible,
is_nothrow_default_constructible,
is_nothrow_move_constructible,
is_nothrow_copy_constructible,
is_nothrow_assignable,
is_nothrow_move_assignable,
is_nothrow_copy_assignable,
is_nothrow_destructible.

众所周知,标准库中的容器在包含的类型上使用这些特征来执行优化(移动而不是复制)。也许其他一些优化,我不知道。对我来说,将 noexcept 说明符添加到适当的构造函数或赋值运算符(当然,如果它们真的不抛出)是有意义的,当您将类与标准容器一起使用时,这些特征将返回 true,并获得性能提升。

我不认为将 noexcept 添加到像 getter 或 setter 这样的普通函数是一个好主意:你会受到性能影响而一无所获。如果您的代码没有抛出并且不使用标准库 - 我的建议:根本不要使用 noexcept 。

于 2015-08-06T08:51:22.493 回答