统一初始化
统一初始化
传统圆括号初始化可能产生歧义,被编译器误解析为函数声明,而列表初始化可避免这一问题。
1 | class Foo {}; |
类似地,对于带参数的场景:
1 | class Bar { |
初始化是指为变量赋予初始值
在 C++中,初始化有多种方式,包括复制初始化和直接初始化。
复制初始化( copy initialization ):使用等号
=进行初始化直接初始化( direct initialization ):使用圆括号
()或花括号{}进行初始化
1 | int a = 1; //(1) 复制初始化(copy initialization) |
C++ 初始化形式中的 (2) (4) 都属于列表初始化,在 C++11 中得到全面应用
初始化和赋值:初始化的等号和赋值的等号含义不同
- 初始化:为变量申请存储空间,创建新的变量。如果是类类型,将调用类的构造函数
- 赋值:把一个现有变量的值用另一个值替代,不创建新的变量。如果是类类型,将调用类的赋值运算符
operator=()
1
2
3
4
5 int a = 1; // 初始化
a = 2; // 赋值
ClassType obj1; // 初始化,调用构造函数
ClassType obj2("Hello"); // 初始化,调用构造函数
obj1 = obj2; // 赋值
- 列表初始化( list initialization ):使用花括号
{}进行初始化
列表初始化的底层支持
C++11 引入的std::initializer_list<T>是列表初始化的核心机制,它本质是一个轻量级容器,用于封装同类型元素的列表。当使用{}初始化时,编译器会自动将列表元素转换为std::initializer_list<T>对象(若元素类型一致)。
- 类中使用
std::initializer_list:若类定义了接受std::initializer_list<T>的构造函数,列表初始化会优先调用该构造函数,即使存在其他更匹配的构造函数。这是列表初始化的特殊优先级规则。
1 |
|
std::initializer_list的特性:
- 元素为
const,无法修改(如list[0] = 5;是错误的)。- 生命周期与初始化列表绑定,超出范围后失效。
- 常用于容器初始化(如
std::vector、std::map),标准库容器均提供接受std::initializer_list的构造函数。
统一初始化特点
统一语法:使用花括号
{}进行初始化,适用于几乎所有类型的初始化。自动避免窄化转换:列表初始化禁止 “窄化转换”(可能导致数据丢失的转换):
从浮点类型到整数类型(如
double→int)。从
long double→double→float(除非源是常量且值在目标范围內)。从整数类型到浮点类型(除非源是常量且值在目标范围內)。
从大整数类型到小整数类型(如
long long→char,且值超出小类型范围)。
1 | long double num = 3.1415; |
- 适于所有类型:包括 POD ( Plain Old Data ,可以被直接使用
memcpy进行复制的对象)类型、聚合类型、类类型等。
1 | //聚合类型(指没有用户自定义的构造函数、析构函数、拷贝构造函数和赋值运算符的类,包括数组、结构体等)初始化: |
聚合类型:
- C++11:聚合类型需满足:无用户定义构造函数、无私有 / 保护非静态成员、无基类、无虚函数。
- C++17:允许包含公共基类(基类也必须是聚合类型)。
- C++20:进一步放松,允许存在用户声明但未定义的构造函数(即
= default或= delete的构造函数)。示例( C++17 及以上):
1
2
3
4 struct Base { int x; };
struct Derived : Base { int y; }; // 聚合类型(C++17允许公共基类)
Derived d{ {1}, 2 }; // 正确:Base的x=1,Derived的y=2
C++17 指定初始化器( Designated Initializers )
C++17 引入了类似 C 语言的 “指定初始化器”,允许通过成员名称初始化聚合类型,顺序可与声明顺序不同。
1 | struct Point { int x; int y; }; |
注意:指定初始化器不能跳过前面的成员(如Point{.y=2}在 C++ 中错误, C 语言允许)。
构造函数与列表初始化的交互
explicit关键字用于禁止构造函数的隐式转换,但对列表初始化的影响需注意:
explicit构造函数不能用于复制初始化(如Bar b = 10;错误)。- 但可以用于直接列表初始化(如
Bar b{10};正确),因为列表初始化属于显式行为。
1 | class Bar { |





