没有除了风格和性能的练习?
noexcept practice for style and performance?
我开始将 noexcept
添加到我的代码中,但我想知道将其添加到内联函数中是否明智。我假设优化器会在明显不需要时忽略运行时检查……但是从 human/style 的角度来看,是否值得将 noexcept 添加到 getter、设置、增量函数等琐碎的函数中?我认为这是完全明显的东西的视觉混乱。我正在讨论内联函数省略 noexcept 的规则,但正常的 .hpp/.cpp 函数如果不抛出则必须拥有它。
其次,我有大量代码根本无法抛出,因为它没有分配(在我的国际象棋引擎中),不包括 STL 或任何其他可能失败的代码,因此始终可以保证成功。 noexcept 不会因为运行时检查而减慢它的速度吗?有没有人使用宏在使用 noexcept
进行 DEBUG
构建之间切换,但切换到 throw()
进行发布,这只是编译时?
如果您的内联函数是一个叶级函数,即它本身不调用任何函数,那么理论上编译器可以确定它不会抛出并忽略可能已经生成的任何异常处理。所以在性能方面,它可能被证明是不必要的。
话虽如此,您不应期望看到添加 noexcept
会导致性能下降。无论必须生成什么代码来处理异常传播,都不应该通过添加 noexcept
变得更加复杂。值得注意的是,如果从 noexcept 函数中抛出异常,则允许编译器完全忽略展开堆栈。这主要是 noexcept
的直接好处的来源。
至于风格推荐,首先要考虑 noexcept
是否对您的界面有用。由于算法原因,诸如移动操作之类的事情可以从 noexcept
中受益匪浅,但除此之外,真正由您决定 noexcept
对您、您的界面和界面用户的价值在哪里。
如果这不能回答您的问题,请随时对我的回答发表评论,我会进一步澄清。
旁注:throw()
除了在 C++11 中被弃用外,还没有提供与 noexcept
相同的保证。如果通过声明为 throw()
的函数抛出异常,则堆栈必须完全展开到该函数的调用者。有关此行为的参考,请参阅 C++ 标准版本 N3337 中的 15.5.2.1。
通过向函数添加 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 说明符添加到适当的构造函数或赋值运算符(当然,如果它们真的不抛出),这些特征将 return 为真,并在使用 [=18= 时获得性能提升] 使用标准容器。
我不认为将 noexcept 添加到像 getter 或 setter 这样的普通函数中是个好主意:你会受到性能影响而一无所获。
如果您的代码没有抛出错误并且没有使用标准库——我的建议是:根本不要使用 noexcept。
我开始将 noexcept
添加到我的代码中,但我想知道将其添加到内联函数中是否明智。我假设优化器会在明显不需要时忽略运行时检查……但是从 human/style 的角度来看,是否值得将 noexcept 添加到 getter、设置、增量函数等琐碎的函数中?我认为这是完全明显的东西的视觉混乱。我正在讨论内联函数省略 noexcept 的规则,但正常的 .hpp/.cpp 函数如果不抛出则必须拥有它。
其次,我有大量代码根本无法抛出,因为它没有分配(在我的国际象棋引擎中),不包括 STL 或任何其他可能失败的代码,因此始终可以保证成功。 noexcept 不会因为运行时检查而减慢它的速度吗?有没有人使用宏在使用 noexcept
进行 DEBUG
构建之间切换,但切换到 throw()
进行发布,这只是编译时?
如果您的内联函数是一个叶级函数,即它本身不调用任何函数,那么理论上编译器可以确定它不会抛出并忽略可能已经生成的任何异常处理。所以在性能方面,它可能被证明是不必要的。
话虽如此,您不应期望看到添加 noexcept
会导致性能下降。无论必须生成什么代码来处理异常传播,都不应该通过添加 noexcept
变得更加复杂。值得注意的是,如果从 noexcept 函数中抛出异常,则允许编译器完全忽略展开堆栈。这主要是 noexcept
的直接好处的来源。
至于风格推荐,首先要考虑 noexcept
是否对您的界面有用。由于算法原因,诸如移动操作之类的事情可以从 noexcept
中受益匪浅,但除此之外,真正由您决定 noexcept
对您、您的界面和界面用户的价值在哪里。
如果这不能回答您的问题,请随时对我的回答发表评论,我会进一步澄清。
旁注:throw()
除了在 C++11 中被弃用外,还没有提供与 noexcept
相同的保证。如果通过声明为 throw()
的函数抛出异常,则堆栈必须完全展开到该函数的调用者。有关此行为的参考,请参阅 C++ 标准版本 N3337 中的 15.5.2.1。
通过向函数添加 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 说明符添加到适当的构造函数或赋值运算符(当然,如果它们真的不抛出),这些特征将 return 为真,并在使用 [=18= 时获得性能提升] 使用标准容器。
我不认为将 noexcept 添加到像 getter 或 setter 这样的普通函数中是个好主意:你会受到性能影响而一无所获。 如果您的代码没有抛出错误并且没有使用标准库——我的建议是:根本不要使用 noexcept。