添加' noexcept(false) '是否对代码有任何好处?

Does adding `noexcept(false)` benefit the code in any way?

本文关键字:代码 任何好 noexcept false 添加 是否      更新时间:2023-10-16

最近在我的代码中,我已经明确地在函数上编写了noexcept(false),我知道会抛出异常,主要是为了阅读代码的人。然而,我想知道这是否会影响我的代码的行为或编译器解释它的方式。这有什么区别吗?

注意:我知道析构函数是隐式的noexcept,你必须指定noexcept(false)来改变它,我想知道其他函数

没有异常说明符和显式声明noexcept(false)是等价的,参见§15.4/12:

没有异常说明或有noexcept(constant-expression)形式的异常说明的函数,其中常量表达式产生false,允许所有异常。

所以编译器在考虑异常时不应该区分它们。


更重要的是,您不需要将noexcept(false)添加到函数中。作为一名c++开发人员,你应该假设每个函数在默认情况下都会抛出(这就是为什么标准采用这种立场),所以你不会通过写出来来添加新信息;这对每个人来说都是浪费时间。

应该用noexcept标记函数肯定不抛出的特殊情况,用noexcept(condition)标记函数根据某些条件可能抛出的情况。

如果你的函数故意成为某些异常E的来源,在你的文档中写出来

我能想到的一个例子是在析构函数中。我知道你永远不应该使用析构函数。但在某些情况下,你会被这样做的代码所困,没有解决办法。

由于c++会自动将noexcept添加到析构函数中,这是撤销它并防止代码抛出时终止应用程序的唯一方法。

https://github.com/chriskohlhoff/asio/issues/1216

从:https://akrzemi1.wordpress.com/2011/09/21/destructors-that-throw/

编译器仍然会在你的析构函数。这意味着当析构函数抛出异常时,std::terminate将被调用,即使没有double-exception情况。如果你真的决定允许你的要抛出析构函数,你必须显式地指定;你有三个选项:

  1. 显式指定你的析构函数为noexcept(false),
  2. 从另一个已经将析构函数指定为noexcept(false)的类继承你的类。
  3. 在你的类中加入一个非静态数据成员,它已经将析构函数指定为noexcept(false)。

Herb Sutter在他的《More Exceptional c++》一书中有以下代码片段(第130页):

例19-1的正确答案要简单得多:
// Example 19-4: The right solution
//
T::~T() /* throw() */
{
 // ... code that won't throw ...
}

示例19-4演示了如何做出设计决策,而不是犹豫不决。

注意throw()不抛出任何异常规范只是一个评论。在某种程度上,这就是我选择遵循的风格因为事实证明异常规范赋予的意义要少得多收益大于价值是否决定实际编写规范是个人喜好的问题。

(强调我的)

因此,我觉得我必须指出,c++异常安全代码的一位主要专家似乎反对添加异常规范供编译器使用(但仍将其留在代码中供程序员理解)的整个概念。

只是觉得这可能是有趣的信息…