Default constructors
默认构造函数是一种 构造函数 ,它可以在没有参数的情况下被调用。
目录 |
语法
class-name
(
parameter-list
(可选)
);
|
(1) | ||||||||
class-name
(
parameter-list
(可选)
)
function-body
|
(2) | ||||||||
class-name
() = default;
|
(3) | (C++11 起) | |||||||
class-name
(
parameter-list
(可选)
) = delete;
|
(4) | (C++11 起) | |||||||
class-name
::
class-name
(
parameter-list
(可选)
)
function-body
|
(5) | ||||||||
class-name
::
class-name
() = default;
|
(6) | (C++11 起) | |||||||
| class-name | - | 声明默认构造函数的类名 |
| parameter-list | - | 一个 参数列表 ,其中所有参数 (除 参数包 外) (C++11 起) 均具有 默认实参 |
| function-body | - | 默认构造函数的 函数体 |
说明
隐式声明的默认构造函数
如果类类型没有用户声明的构造函数或构造函数模板,编译器将隐式声明一个默认构造函数作为其类的 inline public 成员。
隐式声明(或在首次声明时缺省)的默认构造函数具有异常规范,如 动态异常规范 (C++17 前) noexcept 规范 (C++17 起) 所述。
隐式定义的默认构造函数
如果 构造函数是隐式声明的 (C++11 前) 隐式声明或显式预置的默认构造函数未被定义为弃置的 (C++11 起) ,则编译器会在 ODR 使用 或 常量求值需要时 ,或在其首次声明后被显式预置时 (C++11 起) 隐式定义该构造函数。
|
若联合类
|
(since 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没有虚基类。
|
(since 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) {} // 用户定义的默认构造函数 }; struct B : A { // B::B() 是隐式定义的,调用 A::A() }; struct C { A a; // C::C() 是隐式定义的,调用 A::A() }; struct D : A { D(int y) : A(y) {} // D::D() 未声明,因为存在其他构造函数 }; struct E : A { E(int y) : A(y) {} E() = default; // 显式默认,调用 A::A() }; struct F { int& ref; // 引用成员 const int c; // 常量成员 // F::F() 被隐式定义为删除 }; // 用户声明的拷贝构造函数(无论是用户提供、删除还是默认) // 会阻止隐式生成默认构造函数 struct G { G(const G&) {} // G::G() 被隐式定义为删除 }; struct H { H(const H&) = delete; // H::H() 被隐式定义为删除 }; struct I { I(const I&) = default; // I::I() 被隐式定义为删除 }; int main() { A a; B b; C c; // D d; // 编译错误 E e; // F f; // 编译错误 // G g; // 编译错误 // H h; // 编译错误 // I i; // 编译错误 }
缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的C++标准。
| 缺陷报告 | 应用于 | 发布时的行为 | 正确行为 |
|---|---|---|---|
| CWG 1353 | C++11 |
隐式声明的默认构造函数被定义为删除的条件
未考虑多维数组类型 |
考虑这些类型 |
| CWG 2084 | C++11 |
默认成员初始化器对联合体的默认默认构造函数
是否被删除没有影响 |
它们会阻止默认默认构造函数
被删除 |
| CWG 2595 | C++20 |
当存在另一个约束更强但
不满足其关联约束的默认构造函数时, 该默认构造函数不符合条件 |
在此情况下它可能符合条件 |
| CWG 2871 | C++98 |
即使存在用户声明的构造函数模板,
也会隐式声明默认构造函数 |
在此情况下
不进行隐式声明 |