在C++98中,标准容许使用花括号“{}”对数组元素进行统一的集合(列表)初始化设定,好比:程序员
这些都是合法的表达式。不过一些自定义类型,却没法享受着这样便利的初始化。一般,如标准程序库中的vector这样的容器,老是须要声明对象-循环初始化这样的重复动做,这对于使用模板的泛型编程无疑是很是不利的。编程
事实上,在C++11中,集合(列表)的初始化已经成为C++语言的一个基本功能,在C++11中,这种初始化的方法被称为“初始化列表”(initializer list)。一块儿看几个例子。数组
int a[] = { 1,3, 5 }; int b[]{ 2,4,6 }; vector<int> c{ 1,3,5 }; map<int, float> d = { { 1, 1.0f },{ 2, 2.0f } };
在C++11中,因为列表初始化的存在,上面的均可以经过编译。这里,列表初始化能够在“{}”花括号以前使用等号,其效果与不带等号的初始化相同。函数
这样一来,自动变量和全局变量的初始化在C++11中被丰富了。程序员能够使用如下几种形式完成初始化工做:ui
等号“=”加上赋值表达式,好比 int a =3 + 4。spa
等号“=”加上花括号式的初始化列表,好比 int a = { 3 + 4 }。.net
圆括号式的表达式列表,好比 int a (3 + 4)。code
花括号式的初始化列表,好比 int a { 3 + 4 }。对象
这后两种形式也能够用于获取堆内存new操做符中,好比:blog
int *i = new int(1); double *d = new double{1.2f};
读者可能会猜想是否初始化列表是专属于内置类型、数组,以及标准模板库中容器的功能呢?
事实并不是如此,在C++11中,标准老是倾向于使用更为通用的方式来支持新的特性。标准模板库中容器对初始化列表的支持源自<initializer_list>这个头文件中initialize_list类模板的支持。程序员只要#include了<initialize_list>头文件,而且声明一个以initialize_list<T>模板类为参数的构造函数,一样能够使得自定义的类使用列表初始化。看看下面的例子:
#include <map> #include <vector> using namespace std; enum Gender {boy, girl}; class People { public: People(initializer_list<pair<string, Gender>> r) { auto i = r.begin(); for (; i != r.end(); ++i) data.push_back(*i); } private: vector<pair<string, Gender>> data; }; int main() { People ship = { {"Garfield", boy}, {"HelloKitty", girl} }; }
咱们为类People定义了一个使用initialize_list<pair<string,Gender>>模板类做为参数的构造函数。因为这个列表初始化的构造函数的存在,ship声明就能够使用列表初始化了。
一样的,函数的参数列表也能够使用初始化列表,以下例:
#include <map> #include <vector> using namespace std; void Fun(initializer_list<int>iv) {} int main() { Fun({ 1,2 }); Fun({}); //空列表 }
同理,类和结构体的成员函数也能够使用初始化列表,包括一些操做符的重载函数。
此外,初始化列表还能够用于函数返回的状况。返回一个初始化列表,一般会致使构造一个临时变量,好比:
vector<int> Func() { return{ 1,3 }; }
固然,跟声明时采用列表初始化同样,列表初始化构形成什么类型是依据返回类型的,,好比:
deque<int> Func2() { return{ 3.5 }; }
上面的返回值就是以deque<int>列表初始化构造函数而构造的。而若是返回值是一个引用类型的话,则会返回一个临时变量的引用。好比:
const vector<int> &Func1() { return{ 1,3 }; }
参考:<深刻理解C++11>