默认构造函数
默认构造函数是一个可以不带参数调用的 构造函数。
目录 |
[编辑] 语法
类名( 形参列表(可选)); |
(1) | ||||||||
类名( 形参列表(可选)) 函数体 |
(2) | ||||||||
类名() = default; |
(3) | (自 C++11 起) | |||||||
类名( 形参列表(可选)) = delete; |
(4) | (自 C++11 起) | |||||||
类名:: 类名( 形参列表(可选)) 函数体 |
(5) | ||||||||
类名:: 类名() = default; |
(6) | (自 C++11 起) | |||||||
类名 | - | 正在声明其默认构造函数的类 |
形参列表 | - | 形参列表,其中所有形参(除了形参包)(自 C++11 起)都有默认实参 |
函数体 | - | 默认构造函数的函数体 |
[编辑] 解释
[编辑] 隐式声明的默认构造函数
如果类类型没有用户声明的构造函数或构造函数模板,编译器将隐式声明一个默认构造函数作为其类的 inline public 成员。
隐式声明(或在其首次声明时预置)的默认构造函数具有异常规范,如动态异常规范(直到 C++17) noexcept 规范(自 C++17 起)所述。
[编辑] 隐式定义的默认构造函数
如果构造函数是隐式声明的(直到 C++11)隐式声明或显式预置的默认构造函数未定义为已删除(自 C++11 起),则当 ODR 使用或需要进行常量求值时(自 C++11 起),它由编译器隐式定义。
如果类联合体 |
(自 C++26 起) |
一个(直到 C++26)否则,一个(自 C++26 起)隐式定义的默认构造函数具有与用户定义的带有空主体和空初始化器列表的构造函数相同的效果。也就是说,它调用此类的基类和非静态成员的默认构造函数。在值初始化期间,具有空的用户提供构造函数的类类型可能与具有隐式定义的默认构造函数的类类型得到不同的处理。
如果这满足constexpr 构造函数(直到 C++23)constexpr 函数(自 C++23 起)的要求,则生成的构造函数是 constexpr。 如果存在一些用户定义的构造函数,用户仍然可以使用关键字 default 强制编译器自动生成默认构造函数,否则该构造函数将被隐式声明。 |
(自 C++11 起) |
已删除的默认构造函数如果满足以下任何条件,则类
如果没有用户定义的构造函数并且隐式声明的默认构造函数不是平凡的,则用户仍然可以使用关键字 delete 来阻止编译器自动生成隐式定义的默认构造函数。 |
(自 C++11 起) |
[编辑] 平凡默认构造函数
如果满足以下所有条件,则类 T
的默认构造函数是平凡的
- 构造函数是隐式声明的(直到 C++11)不是用户提供的(自 C++11 起)。
-
T
没有虚成员函数。 -
T
没有虚基类。
|
(自 C++11 起) |
T
的每个直接基类都有一个平凡默认构造函数。
|
(直到 C++26) |
|
(自 C++26 起) |
平凡默认构造函数是不执行任何操作的构造函数。与 C 语言兼容的所有数据类型(POD 类型)都是可平凡默认构造的。
[编辑] 合格默认构造函数
如果默认构造函数是用户声明的,或者既是隐式声明的又是可定义的,则它是合格的。 |
(直到 C++11) |
如果默认构造函数未被删除,则它是合格的。 |
(自 C++11 起) (直到 C++20) |
如果满足以下所有条件,则默认构造函数是合格的 |
(自 C++20 起) |
合格默认构造函数的平凡性决定了该类是否为隐式生存期类型,以及该类是否为可平凡复制类型。
[编辑] 注解
特性测试宏 | 值 | Std | 特性 |
---|---|---|---|
__cpp_trivial_union |
202502L |
(C++26) | 放宽联合体的特殊成员函数的平凡性要求 |
[编辑] 示例
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++11 | 隐式声明的默认构造函数为 定义为已删除的条件没有考虑多维数组类型 |
考虑这些类型 |
CWG 2084 | C++11 | 默认成员初始化器对是否 联合体的预置默认构造函数被删除没有影响 |
它们阻止预置默认 构造函数被删除 |
CWG 2595 | C++20 | 如果存在 另一个约束更多的默认构造函数,则默认构造函数不合格 但不满足其关联约束 |
在这种情况下它可以是合格的 |
CWG 2871 | C++98 | 即使存在用户声明的构造函数模板,也会隐式声明默认构造函数 即使存在用户声明的构造函数模板,也会隐式声明默认构造函数 |
无隐式声明 在这种情况下 |