最近在我的代码中,我已经显式地为我知道会抛出异常的函数编写了noexcept(false),主要是为了阅读代码的人。然而,我想知道这是否会影响代码的行为或编译器解释它的方式。这有什么不同吗?注意:我知道析构函数是隐式的noexcept,并且你必须指定noexcept(false)来改变这一点,我想知道其他函数。
noexcept(false)
bfrts1fy1#
没有异常说明符和显式声明noexcept(false)是等价的,参见§15.4/12:没有异常说明或具有形式为noexcept(constant-expression)的异常说明(其中常量表达式产生false)的函数允许所有异常。因此编译器在考虑异常时不应区分它们。更重要的是,你不需要在你的函数上附加noexcept(false),作为一个C++开发人员,你应该假设每个函数默认抛出(这就是为什么标准采取这种立场),所以你写出来并没有增加新的信息;对大家来说都是浪费时间。相反,要用noexcept标记函数 * 绝对 * 不抛出的特殊情况,并用noexcept(condition)标记函数 * 可能 * 根据某些条件抛出的情况。如果您的函数是某个异常E的源,请在文档中注明。
noexcept(constant-expression)
false
noexcept
noexcept(condition)
E
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)。
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似乎反对添加异常规范供编译器使用(但仍将其留在代码中供程序员理解)的整个概念。只是觉得这可能是有趣的信息...
throw()
3条答案
按热度按时间bfrts1fy1#
没有异常说明符和显式声明
noexcept(false)
是等价的,参见§15.4/12:没有异常说明或具有形式为
noexcept(constant-expression)
的异常说明(其中常量表达式产生false
)的函数允许所有异常。因此编译器在考虑异常时不应区分它们。
更重要的是,你不需要在你的函数上附加
noexcept(false)
,作为一个C++开发人员,你应该假设每个函数默认抛出(这就是为什么标准采取这种立场),所以你写出来并没有增加新的信息;对大家来说都是浪费时间。相反,要用
noexcept
标记函数 * 绝对 * 不抛出的特殊情况,并用noexcept(condition)
标记函数 * 可能 * 根据某些条件抛出的情况。如果您的函数是某个异常
E
的源,请在文档中注明。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)。
mf98qq943#
在他的书More Exceptional C++中,Herb Sutter有以下片段(第130页):
例19 - 1的正确答案要简单得多:
例19 - 4演示了如何做出设计决策,而不是含糊其辞。
注意,
throw()
throws-nothing异常规范只是一个注解。**这是我选择遵循的风格,部分原因是异常规范带来的好处远远小于它们的价值。**是否决定实际编写该规范是一个品味问题。(着重号是我的)
因此,我觉得我必须指出,C++异常安全代码方面的一位主要Maven似乎反对添加异常规范供编译器使用(但仍将其留在代码中供程序员理解)的整个概念。
只是觉得这可能是有趣的信息...