C++11大括号初始化
C++11大括号初始化
C++11 大括号初始化
C++11 可以将 {} 初始化器用于任何类型(可以用等号,也可以不用)
数组、集合初始化
在 C++11 中,集合(列表)的初始化已经成为 C++ 的一个基本功能,被称为“初始化列表”:
1
2
3
4
5
6
7
8
9
10
// C++98支持,C++11支持
int a[] = {1, 2, 3};
// C++98不支持,C++11支持
int b[]{2, 3, 4};
// C++98不支持,C++11支持
vector<int> c{1, 2, 3};
// C++98不支持,C++11支持
map<int, float> d = { {1, 1.0f},
{2, 2.0f},
{3, 3.0f}};
在 C++11 中,自动变量和全局变量的初始化方式包括:
1
2
3
4
5
6
7
8
9
10
// 1.等号加上赋值表达式
int t1 = 1 + 2;
// 2.等号加上大括号表达式的初始化列表
int t2 = {1 + 2};
// 3.大括号式的初始化列表
int t3{1 + 2};
int *t4 = new int{10};
// 4.小括号式的表达式列表
int t6(3 + 4);
int *t7 = new int(10);
类成员初始化
C++98 中如果静态成员不满足常量性,不能就地声明,且而且即使常量的静态成员也只能是整型或枚举型才能就地初始化。
C++11 中,除了初始化列表(在构造函数中初始化)外,允许使用等 = 或花括号 {} 进行就地的非静态成员变量初始化:
1
2
3
struct Node {
int value = 1;
};
如果在一个类中,既使用了就地初始化来初始化非静态成员变量,又在构造函数中使用了初始化列表,执行顺序是:先执行就地初始化,然后执行初始化列表。
自定义类型初始化
标准模板库 STL中 容器对初始化列表的支持源于 <initializer_list>
头文件中initialize_list
类模板的支持。程序员只要 #include <initializer_list>
并声明一个以 initialize_List<T>
模板类为参数的构造函数,也可以使得自定义类使用列表初始化。
默认初始化 vs 值初始化 vs 零初始化
默认初始化(Default Initialization)
默认初始化发生在 声明一个对象而不带任何初始化器 时,例如:
1
T t; // 默认初始化
对象类型 | 行为 |
---|---|
类类型(有默认构造函数或编译器合成的) | 调用默认构造函数(user-defined 或 compiler-generated) |
内置类型(int, double, pointer 等) | 不初始化(自动存储期对象是未定义值,堆栈上可能是垃圾值) |
静态存储期的对象 | 自动进行零初始化(静态区全 0)后再调用默认构造(如果是类类型) |
属性 | 自动存储期 | 静态存储期 |
---|---|---|
声明位置 | 函数或块内局部 | 全局、static 局部、类静态成员 |
生命周期 | 进入作用域开始 → 离开作用域结束 | 程序开始 → 程序结束 |
内置类型初始化 | 默认未初始化(垃圾值) | 自动零初始化 |
分配位置 | 栈 | 静态/数据区 |
1
2
3
4
5
6
7
8
struct A { int x; A() { x = 42; } };
struct B { int y; }; // POD
int main() {
A a; // 调用 A(),a.x == 42
B b; // 未初始化,b.y 是垃圾值
int n; // 未初始化,n 是垃圾值
}
值初始化(Value Initialization)
值初始化通常出现在 使用 {}
或 ()
形式初始化对象时:
1
2
T t{}; // 推荐 C++11 及以后
T t(); // 注意!这是函数声明,非对象初始化
对象类型 | 行为 |
---|---|
类类型(有默认构造函数) | 调用默认构造函数 |
类类型(POD 或无默认构造) | 零初始化,然后按需要调用构造函数 |
内置类型 | 零初始化(初始化为 0) |
1
2
3
4
5
6
7
8
struct A { int x; };
struct B { int y; B() {} };
int main() {
A a{}; // POD,先零初始化,a.x == 0
B b{}; // B() 被调用,如果 B() 不初始化 y,则 y 是垃圾值
int n{}; // n == 0
}
注意:T t();
在 C++ 中是 函数声明(最著名的 Most Vexing Parse),不会创建对象。
零初始化(Zero Initialization)
零初始化是 把对象的所有内置类型成员和指针清零 的操作,通常是值初始化的一部分,也会自动发生在静态/全局对象中。
- 对 内置类型:设置为
0
(整型)、0.0
(浮点型)、nullptr
(指针) - 对 类类型:先对 POD 成员零初始化,然后调用默认构造函数(如果有)
1
2
3
4
5
6
struct A { int x; double y; };
static A a_static; // 静态存储期,先零初始化:x=0, y=0.0
int main() {
A a{}; // 值初始化,先零初始化 x=0, y=0.0
}
三者的执行顺序关系
以 T t{};
为例,值初始化执行步骤大致如下:
- 零初始化:将对象内存全部清 0
- 调用默认构造函数(如果类类型有默认构造)
- 构造函数体执行(合成或用户定义)
而 T t;
(默认初始化)则跳过第一步,直接调用默认构造函数(或对内置类型保持未定义值)。
本文由作者按照 CC BY 4.0 进行授权