初始化列表

在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>