默认构造函数
默认构造函数是一种可以不带参数调用的 构造函数。
目录 |
[编辑] 语法
类名 ( 参数列表 (可选)); |
(1) | ||||||||
类名 ( 参数列表 (可选)) 函数体 |
(2) | ||||||||
类名 () = default; |
(3) | (自 C++11 起) | |||||||
类名 ( 参数列表 (可选)) = delete; |
(4) | (自 C++11 起) | |||||||
类名 :: 类名 ( 参数列表 (可选)) 函数体 |
(5) | ||||||||
类名 :: 类名 () = default; |
(6) | (自 C++11 起) | |||||||
类名 | - | 正在声明其默认构造函数的类 |
参数列表 | - | 一个参数列表,其中所有参数(参数包除外)(自 C++11 起)都具有默认参数 |
函数体 | - | 默认构造函数的函数体 |
[编辑] 说明
[编辑] 隐式声明的默认构造函数
如果类类型没有用户声明的构造函数或构造函数模板,编译器将隐式声明一个默认构造函数,作为其类的内联 公共成员。
隐式声明的(或在其第一次声明时默认的)默认构造函数具有动态异常规范(直到 C++17)noexcept 规范(自 C++17 起)中所描述的异常规范。
[编辑] 隐式定义的默认构造函数
如果构造函数是隐式声明的(直到 C++11)隐式声明或显式默认的默认构造函数未被定义为删除(自 C++11 起),则编译器会在odr 使用或常量求值所需(自 C++11 起)时定义它(即生成并编译函数体),并且它的效果与具有空函数体和空初始化列表的用户定义构造函数相同。也就是说,它调用基类和此类的非静态成员的默认构造函数。具有空用户提供的构造函数的类类型在值初始化期间的处理方式可能与具有隐式定义的默认构造函数的类类型不同。
如果这满足constexpr 构造函数(直到 C++23)constexpr 函数(自 C++23 起)的要求,则生成的构造函数为constexpr。 如果存在一些用户定义的构造函数,用户仍然可以通过关键字default强制编译器自动生成默认构造函数,否则该构造函数将被隐式声明。 |
(自 C++11 起) |
[编辑] 已删除的默认构造函数
类T
的隐式声明的或显式默认的(自 C++11 起)默认构造函数在以下任一条件满足时未定义(直到 C++11)被定义为已删除(自 C++11 起):
-
T
是一个联合体,并且它的所有变体成员都是 const 限定类型(或者可能是其多维数组)。 -
T
是一个非联合体类,并且任何匿名联合体成员的所有成员都是 const 限定类型(或者可能是其多维数组)。 -
T
具有一个没有默认初始化器的非静态引用类型数据成员(自 C++11 起)。 -
T
具有一个没有默认成员初始化器的非变体、非静态、非const-default-constructible、const 限定类型(或者可能是其多维数组)的数据成员(自 C++11 起)。 -
T
具有一个类类型M
(或者可能是其多维数组)的潜在构造子对象,使得
-
M
的析构函数被删除或(自 C++11 起)无法从默认构造函数访问,或者 - 以下所有条件均满足:
-
|
(自 C++11 起) |
- 用于查找
M
的默认构造函数的重载决议
- 没有产生可用的候选函数,或者
- 在子对象是变体成员的情况下,选择了一个非平凡函数。
- 用于查找
如果不存在用户定义的构造函数,并且隐式声明的默认构造函数不是平凡的,则用户仍然可以使用关键字 delete 来阻止编译器自动生成隐式定义的默认构造函数。 |
(自 C++11 起) |
[编辑] 平凡的默认构造函数
如果满足以下所有条件,则类 T
的默认构造函数是平凡的(即不执行任何操作):
- 构造函数不是用户提供的(即,在其第一次声明时是隐式定义或默认的)。
-
T
没有虚成员函数。 -
T
没有虚基类。
|
(自 C++11 起) |
T
的每个直接基类都有一个平凡的默认构造函数。- 类类型(或其数组)的每个非静态成员都有一个平凡的默认构造函数。
平凡的默认构造函数是不执行任何操作的构造函数。所有与 C 语言兼容的数据类型(POD 类型)都是平凡默认可构造的。
[编辑] 合格的默认构造函数
如果默认构造函数是用户声明的,或者既是隐式声明的又是可定义的,则它是合格的。 |
(直到 C++11) |
如果默认构造函数未被删除,则它是合格的。 |
(自 C++11 起) (直到 C++20) |
如果满足以下所有条件,则默认构造函数是合格的: |
(自 C++20 起) |
合格的默认构造函数的平凡性决定了该类是否是 隐式生命周期类型,以及该类是否是 平凡类型。
[编辑] 示例
struct A { int x; A(int x = 1): x(x) {} // user-defined default constructor }; struct B : A { // B::B() is implicitly-defined, calls A::A() }; struct C { A a; // C::C() is implicitly-defined, calls A::A() }; struct D : A { D(int y) : A(y) {} // D::D() is not declared because another constructor exists }; struct E : A { E(int y) : A(y) {} E() = default; // explicitly defaulted, calls A::A() }; struct F { int& ref; // reference member const int c; // const member // F::F() is implicitly defined as deleted }; // user declared copy constructor (either user-provided, deleted or defaulted) // prevents the implicit generation of a default constructor struct G { G(const G&) {} // G::G() is implicitly defined as deleted }; struct H { H(const H&) = delete; // H::H() is implicitly defined as deleted }; struct I { I(const I&) = default; // I::I() is implicitly defined as deleted }; int main() { A a; B b; C c; // D d; // compile error E e; // F f; // compile error // G g; // compile error // H h; // compile error // I i; // compile error }
[编辑] 缺陷报告
以下行为更改缺陷报告已追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 发布时的行为 | 正确行为 |
---|---|---|---|
CWG 1353 | C++98 | 隐式声明的默认构造函数未定义的条件 未考虑多维数组类型 |
考虑这些类型 |
CWG 2084 | C++11 | 默认成员初始值设定项对以下内容没有影响 联合的默认默认构造函数是否被删除 |
它们阻止了默认的默认 构造函数被删除 |
CWG 2595 | C++20 | 如果存在以下情况,则默认构造函数不合格 另一个默认构造函数更受约束 但不满足其关联的约束 |
在这种情况下它可能是合格的 |
CWG 2871 | C++98 | 即使存在用户声明的构造函数模板,默认构造函数也会被隐式声明 |
在这种情况下没有隐式声明 |