在 c++11 之前,初始化一个变量或对象的方式五花八门:等号赋值、括号传参、大括号给数组赋初值……不仅繁琐,还容易让人记混。c++11 带着“大一统”的使命走来,彻底改变了这一切。
在 c++98 中,标准允许使用花括号 {} 对数组或者结构体元素进行统一的列表初始值设定。比如 int array1[] = {1, 2, 3}; 或是给结构体赋值 point p = {1, 2};。
但是到了 c++11,这种大括号 {}(初始化列表)的使用范围被极大地扩大了,使其可用于所有的内置类型和用户自定义的类型。这就是我们今天要聊的——统一列表初始化。
一、 一切皆可{}
在 c++11 中,使用初始化列表时,可添加等号(=),也可不添加。这种语法不仅适用于基础变量,连数组和 new 表达式也能完美适配。
// 基础变量初始化,可以不要等号!
int x1 = 1;
int x2{ 2 }; // c++11 新玩法
// 数组初始化,同样可以省去等号
int array1[]{ 1, 2, 3, 4, 5 };
int array2[5]{ 0 }; // 全部初始化为0
// 自定义结构体
struct point { int _x; int _y; };
point p{ 1, 2 };
// c++11 中列表初始化也可以适用于 new 表达式中
int* pa = new int[4]{ 0 };
二、 自定义类型,自动调用构造函数
对于类(class)对象,c++11 同样支持这种写法。创建对象时也可以使用列表初始化方式调用构造函数初始化。
假设我们有一个 date 类:
class date {
public:
date(int year, int month, int day)
: _year(year), _month(month), _day(day) {
cout << "date(int year, int month, int day)" << endl;
}
private:
int _year;
int _month;
int _day;
};
int main() {
date d1(2022, 1, 1); // old style:传统的括号传参
// c++11 支持的列表初始化,这里会调用构造函数初始化
date d2{ 2022, 1, 2 };
date d3 = { 2022, 1, 3 };
return 0;
}
以前给对象传参必须用小括号 (),现在用大括号 {} 一样可以精准触发对应的构造函数,代码风格得到了史诗级的统一!
三、 幕后操作:std::initializer_list
为什么 c++11 的 {} 这么强大?当我们写下 auto il = { 10, 20, 30 }; 时,这个等号右边的 {} 到底是个什么东西?
答案是:它的类型是 std::initializer_list。


你可以把它理解为一个轻量级的、用来接收大括号列表的系统内置类型。它的出现,彻底盘活了 stl 容器的初始化。
四、 玩转 stl 容器:告别繁琐的 push_back
std::initializer_list 一般是作为构造函数的参数。c++11 对 stl 中的不少容器就增加了以 std::initializer_list 作为参数的构造函数,这样初始化容器对象就更方便了。同时,它也可以作为 operator= 的参数,这样就可以用大括号赋值。
在没有 c++11 之前,初始化一个 vector 往往需要先定义,再一行行地 push_back,十分痛苦。现在,一行代码搞定:
// 丝滑的容器初始化
vector<int> v = { 1, 2, 3, 4 };
list<int> lt = { 1, 2 };
// 连 map 这种键值对容器也能轻松驾驭
// 这里 {"sort", "排序"} 会先初始化构造一个 pair 对象
map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
// 使用大括号对容器赋值
v = { 10, 20, 30 };
总结
c++11 的统一列表初始化不仅仅是“少写一个等号”这么简单的语法糖。它通过扩展 {} 的使用范围,并引入底层的 std::initializer_list,彻底打通了内置类型、自定义类和 stl 容器之间的初始化壁垒,让 c++ 的代码变得更加现代、简洁和优雅。
到此这篇关于c++11 统一列表初始化的实现的文章就介绍到这了,更多相关c++11 统一列表初始化内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论