c++ 添加'noexcept(false)'是否对代码有益?

plicqrtu  于 2023-02-06  发布在  其他
关注(0)|答案(3)|浏览(140)

最近在我的代码中,我已经显式地为我知道会抛出异常的函数编写了noexcept(false),主要是为了阅读代码的人。然而,我想知道这是否会影响代码的行为或编译器解释它的方式。这有什么不同吗?
注意:我知道析构函数是隐式的noexcept,并且你必须指定noexcept(false)来改变这一点,我想知道其他函数。

bfrts1fy

bfrts1fy1#

没有异常说明符和显式声明noexcept(false)是等价的,参见§15.4/12:
没有异常说明或具有形式为noexcept(constant-expression)的异常说明(其中常量表达式产生false)的函数允许所有异常。
因此编译器在考虑异常时不应区分它们。
更重要的是,你不需要在你的函数上附加noexcept(false),作为一个C++开发人员,你应该假设每个函数默认抛出(这就是为什么标准采取这种立场),所以你写出来并没有增加新的信息;对大家来说都是浪费时间。
相反,要用noexcept标记函数 * 绝对 * 不抛出的特殊情况,并用noexcept(condition)标记函数 * 可能 * 根据某些条件抛出的情况。
如果您的函数是某个异常E的源,请在文档中注明。

6pp0gazn

6pp0gazn2#

我能想到的一个例子是析构函数。我知道你永远不应该抛出析构函数。但在某些情况下,你会被这样做的代码卡住,没有解决办法。
由于c++会自动给析构函数添加noexcept,这是唯一的方法来撤销它,并防止代码抛出时app终止。
https://github.com/chriskohlhoff/asio/issues/1216
来自:https://akrzemi1.wordpress.com/2011/09/21/destructors-that-throw/
编译器仍然会在你的析构函数中添加noexcept规范,这意味着当你的析构函数抛出异常时,std::terminate将被调用,即使没有双重异常的情况,如果你真的决定允许你的析构函数抛出异常,你必须显式地指定它;你有三个选择:
1.显式地将析构函数指定为noexcept(false),
1.从另一个已经将析构函数指定为noexcept(false)的类继承您的类。
1.在类中放入一个非静态数据成员,该成员已经将其析构函数指定为noexcept(false)。

mf98qq94

mf98qq943#

在他的书More Exceptional C++中,Herb Sutter有以下片段(第130页):
例19 - 1的正确答案要简单得多:

// Example 19-4: The right solution
//
T::~T() /* throw() */
{
 // ... code that won't throw ...
}

例19 - 4演示了如何做出设计决策,而不是含糊其辞。
注意,throw() throws-nothing异常规范只是一个注解。**这是我选择遵循的风格,部分原因是异常规范带来的好处远远小于它们的价值。**是否决定实际编写该规范是一个品味问题。
(着重号是我的)
因此,我觉得我必须指出,C++异常安全代码方面的一位主要Maven似乎反对添加异常规范供编译器使用(但仍将其留在代码中供程序员理解)的整个概念。
只是觉得这可能是有趣的信息...

相关问题