Namespaces
Variants

Default constructors

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Default constructor
Copy constructor
Move constructor (C++11)
Templates
Miscellaneous

默认构造函数是一种 构造函数 ,它可以在没有参数的情况下被调用。

目录

语法

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 - 默认构造函数的 函数体

说明

1) 在类定义内部声明默认构造函数。
2-4) 类定义内默认构造函数的定义。
3) 默认构造函数被显式默认化。
4) 默认构造函数被删除。
5,6) 在类定义外部定义默认构造函数(该类必须包含声明 (1) )。
6) 默认构造函数被显式默认化。

默认构造函数在 默认初始化 值初始化 期间被调用。

隐式声明的默认构造函数

如果类类型没有用户声明的构造函数或构造函数模板,编译器将隐式声明一个默认构造函数作为其类的 inline public 成员。

隐式声明(或在首次声明时缺省)的默认构造函数具有异常规范,如 动态异常规范 (C++17 前) noexcept 规范 (C++17 起) 所述。

隐式定义的默认构造函数

如果 构造函数是隐式声明的 (C++11 前) 隐式声明或显式预置的默认构造函数未被定义为弃置的 (C++11 起) ,则编译器会在 ODR 使用 常量求值需要时 ,或在其首次声明后被显式预置时 (C++11 起) 隐式定义该构造函数。

若联合类 T 的默认构造函数是平凡的,则对于每个联合 U (其为 T T 的匿名联合成员),若 U 的首个变体成员(若存在)具有隐式生存期类型,则 T 的默认构造函数将开始该成员的生存期(若其不是其联合的活跃成员)。

(since C++26)

一个 (直至 C++26) 否则,一个 (自 C++26 起) 隐式定义的默认构造函数与具有空函数体和空初始化列表的用户定义构造函数具有相同效果。即,它会调用基类及本类非静态成员的默认构造函数。在 值初始化 过程中,具有空用户提供构造函数的类类型可能会与具有隐式定义默认构造函数的类类型被区别对待。

若此满足 constexpr 构造函数 (C++23 前) constexpr 函数 (C++23 起) 的要求,则生成的构造函数为 constexpr

若存在某些用户定义的构造函数,用户仍可通过关键字 default 强制编译器自动生成本应隐式声明的默认构造函数。

(C++11 起)


被删除的默认构造函数

当满足以下任意条件时,类 T 的隐式声明或显式预置的默认构造函数会被定义为已删除:

  • T 存在无默认初始化器的引用类型非静态数据成员。
  • T 是非联合体类且 (C++26 起) 存在无默认成员初始化器的 const 限定类型(或其可能的多维数组)的非变体非静态非 常量默认构造 数据成员。
  • T 联合体 且其所有变体成员均为 const 限定类型(或其可能的多维数组)。
  • T 是非联合体类且其任意 匿名联合体 成员的所有成员均为 const 限定类型(或其可能的多维数组)。
(C++26 前)
  • 给定类类型 M T 存在类型为 M (或其可能的多维数组)的 潜在构造子对象 obj ,且满足以下任意条件:
  • M 的析构函数被删除或无法从默认构造函数访问 ,且 obj 是非变体成员或 obj 具有默认成员初始化器 (C++26 起)
  • 同时满足以下所有条件:
  • obj 不是带默认初始化器的非静态数据成员。
  • obj 不是联合体的变体成员 (且该联合体中其他非静态数据成员具有默认初始化器) (C++26 前)
  • 为查找 M 的默认构造函数而进行的重载决议未得到可用候选 ,或在 obj 为变体成员时选择了非平凡函数 (C++26 前)

若不存在用户定义的构造函数且隐式声明的默认构造函数非平凡,用户仍可通过 delete 关键字阻止编译器自动生成隐式定义的默认构造函数。

(C++11 起)

平凡默认构造函数

当满足以下所有条件时,类 T 的默认构造函数是平凡的:

  • 该构造函数是 隐式声明的 (C++11 前) 用户提供 (C++11 起)
  • T 没有虚成员函数。
  • T 没有虚基类。
  • T 没有带有默认初始化器的非静态成员。
(since C++11)
  • T 的每个直接基类都具有平凡的默认构造函数。
  • 每个类类型(或其数组)的非静态成员都拥有平凡的默认构造函数。
(直至 C++26)
  • 满足以下任一条件: T 是联合体类型,或者每个非变体非静态成员(类类型或其数组)都拥有平凡的默认构造函数。
(自 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 即使存在用户声明的构造函数模板,
也会隐式声明默认构造函数
在此情况下
不进行隐式声明

参见