C ++ 11规范很清楚,隐式生成的特殊函数(即默认构造函数,析构函数,复制/移动构造函数和复制/移动赋值运算符)具有异常规范。但规范似乎只是根据现已弃用的动态异常规范(即“throw(T1,T2,T3)”)来编写。这由15.4 / 14中的示例支持:
struct A {
A();
A(const A&) throw();
A(A&&) throw();
~A() throw(X);
};
struct B {
B() throw();
B(const B&) throw();
B(B&&) throw(Y);
~B() throw(Y);
};
struct D : public A, public B {
// Implicit declaration of D::D();
// Implicit declaration of D::D(const D&) throw();
// Implicit declaration of D::D(D&&) throw(Y);
// Implicit declaration of D::D() throw(X, Y);
};
我知道,注释不是规范性的,但值得注意的是,D的复制构造函数被声明为throw()
而不是noexcept
。这会有所不同,因为如果违反throw()
与违反noexcept
,则程序的行为会有所不同。
示例上方15.4 / 14中的文字是规范性的,并且说:
隐式声明的特殊成员函数(第12条) 应有例外规范。如果f是隐式声明的 默认构造函数,复制构造函数,移动构造函数,析构函数, 复制赋值运算符,或移动赋值运算符,其隐式 exception-specification指定type-id T当且仅当T为时 直接调用的函数的异常规范允许 通过f的隐含定义;如果有的话,f应允许所有例外 函数它直接调用允许所有异常,并且f应允许 如果它直接调用的每个函数都不允许没有例外 异常。
鉴于此处仅引用动态异常规范,我担心隐式生成的特殊成员函数永远不会被声明为noexcept
。那是真的吗?
答案 0 :(得分:1)
我不相信是这样的。实际要求只是“......如果它直接调用的每个函数都不允许例外,则不允许例外。”
如上所述(§15.4/ 12):
如果异常规范的格式为
throw()
,noexcept
或noexcept(
常量表达式)
,则该规范不会丢弃其中常量表达式产生true
。具有非抛出异常规范的函数不允许任何异常。
非投掷异常规范不允许任何异常,这并不是一个启示,但我认为这说明非抛出异常规范描述中的措辞几乎逐字逐句地在隐含声明的要求中得到回应特别会员功能。因此,在我看来,任何形式的非抛出异常规范(throw()
或noexcept
或noexcept(<anything that converts to true>)
)都是允许的 - 并且这是特别预期的,而不仅仅是意外措辞。