列表初始化
基本语法
在 C 中我们经常见到如下方式的数组初始化方式和结构体初始化方式:
这个大括号括起来的列表就被用作初始化数组 a
和结构体 b
,而 C++11 中扩大了该列表的适用范围,使其可以初始化所有内置类型和用户自定义类型,并且在 C++11 中, =
也可被省略,如下:
// 内置类型
int a[4] { 1, 2, 3, 4 };
double b = { 4.91 };
int c { 4 };
// 用户自定义类型
class Date
{
int Y,M,D;
public:
Date(int y,int m,int d):Y(y),M(m),D(d){}
};
Date a { 2024, 4, 6 };
对于用户自定义类型,列表初始化会自动调用参数匹配的构造函数。
缩窄检查
我们使用一般的方式对数据进行初始化时,编译器允许程序员执行下面的操作:
在使用 {}
对变量进行初始化时,可以防止类型缩窄,即禁止将数值赋值给无法存储它的变量,并且使用类型不匹配的变量初始化时也会报 Warning,如下:
char a1 = { 1000000 }; // compile error:from 'int' to 'char' inside { }
char a2 = { 67.775 }; // compile error:from 'double' to 'char' inside { }
double b = 67.775;
char c = { b }; // Warning:from 'double' to 'char' inside { }
{}
初始化允许类型转换为更宽的类型。另外只要在较窄类型的范围内,类型转换也是允许的。
std::initializer_list
C++11 提供了模板类 std::initializer_list
,它是一个类似数组的容器,列表中的元素必须是同一类型,通过下面不定个数参数求和的例子理解 std::initializer_list
:
# include <iostream>
int sum(std::initializer_list<int> li)
{
int s = 0;
for(auto it = li.begin();it != li.end();it++)
s += *it;
return s;
}
int main()
{
std::cout << sum({ 1, 2, 3, 4 }) << '\n';
return 0;
}
// 输出: 10
当一个类含有接受 std::initializer_list
为参数的构造函数时,则列表初始化语法就只能用于调用该构造函数。C++11 中 STL 容器都提供了 std::initializer_list
为参数的构造函数,所以我们可以像构造数组一样构造容器: