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()
它会有所不同,因为如果违反 a 与违反a ,程序的行为是不同的noexcept
。
示例上方 15.4/14 中的文本是规范性的,它说:
隐式声明的特殊成员函数(第 12 条)应具有异常规范。如果 f 是隐式声明的默认构造函数、复制构造函数、移动构造函数、析构函数、复制赋值运算符或移动赋值运算符,则其隐式异常规范指定类型 ID T 当且仅当 T 的异常规范允许f 的隐式定义直接调用的函数;如果 f 直接调用的任何函数允许所有异常,则 f 应允许所有异常;如果 f 直接调用的每个函数都不允许异常,则 f 应不允许异常。
鉴于这里只提到了动态异常规范,我担心隐式生成的特殊成员函数永远不会被声明noexcept
。真的是这样吗?