默认构造函数
默认构造函数是无需任何实参即可调用的构造函数。
目录 |
[编辑] 语法
类名 ( 参数列表 (可选)); |
(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 起)时,编译器会隐式定义它。
如果类联合`T`的默认构造函数是平凡的,那么对于每个联合`U`,如果`U`是`T`或`T`的匿名联合成员,如果`U`的第一个变体成员(如果有)具有隐式生命周期类型,则`T`的默认构造函数将开始该成员的生命周期,如果它不是其联合的活跃成员。 |
(C++26 起) |
一个(C++26 前)否则,一个(C++26 起)隐式定义的默认构造函数具有与带有空函数体和空初始化列表的用户定义构造函数相同的效果。也就是说,它调用基类和此类的非静态成员的默认构造函数。带有空用户提供构造函数的类类型在值初始化期间可能与带有隐式定义默认构造函数的类类型被不同对待。
如果这满足constexpr 构造函数(C++23 前)constexpr 函数(C++23 起)的要求,则生成的构造函数是constexpr。 如果存在一些用户定义的构造函数,用户仍然可以通过关键字default强制编译器自动生成原本会隐式声明的默认构造函数。 |
(C++11 起) |
已删除的默认构造函数如果满足以下任何条件,则类`T`的隐式声明或显式默认化的默认构造函数被定义为已删除
如果不存在用户定义的构造函数,并且隐式声明的默认构造函数不是平凡的,用户仍然可以使用关键字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 起) |
合格默认构造函数的平凡性决定了该类是否是隐式生命周期类型,以及该类是否是平凡可复制类型。
[编辑] 注释
功能测试宏 | 值 | 标准 | 特性 |
---|---|---|---|
__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++ 标准。
缺陷报告 | 应用于 | 发布时的行为 | 正确的行为 |
---|---|---|---|
CWG 1353 | C++11 | 隐式声明的默认构造函数在以下情况下被 定义为已删除,但未考虑多维数组类型 |
考虑这些类型 |
CWG 2084 | C++11 | 默认成员初始化器对联合的默认构造函数是否 被删除没有影响 |
它们阻止了默认 构造函数被删除 |
CWG 2595 | C++20 | 如果存在另一个约束更严格的默认构造函数,则默认构造函数不合格 另一个约束更严格的默认构造函数 则拷贝构造函数不合格 |
它在这种情况下可以合格 |
CWG 2871 | C++98 | 即使存在用户声明的构造函数模板,也会隐式声明默认构造函数 即使存在用户声明的构造函数模板 |
无隐式声明 在这种情况下 |