c++11中,初始化列表的使用范围被大大增强了。
首先看看聚合类型定义:
1.类型是一个普通数组(如int[3])
2.类型是一个类(class、struct、union)且
无用户自定义的构造函数
无私有或保护的非静态数据成员
无基类
无虚函数
自定义的构造函数:
struct B
{
int x;
int y;
B(int, int)
: x(0)
, y(0)
{
}
}b = { 123, 321 }; //b.x=0,b.y=0;
保护的非静态成员变量:
struct ss
{
int x;
protected:
double z;
};
ss s{ 1, 3.2 }; //error
保护的静态成员变量:
struct foo
{
int x;
double z;
protected:
static double f;
};
foo f{ 1, 2.2 }; //ok
注意foo中的静态成员不能通过初始化列表的方式进行初始化,它的初始化需要遵循静态成员的初始化方式。
带虚函数和基类
struct ss
{
int x;
virtual void F(){}
};
ss s{ 1 }; //error
struct Base {};
struct foo : public Base
{
int x;
double z;
};
foo f{ 1, 2.2 }; //error
对于一个非聚合类型,不能直接使用初始化列表。要想使用初始化列表,可以自定义构造函数。
另外,聚合类型的定义是非递归的。
struct S
{
int x;
private:
int y;
};
S s{ 1,1 }; //error
struct SS
{
S st;
int x;
};
SS s{ {}, 2 }; //ok
初始化列表可以任意长度:
std::vector<int> ss{ 1,2,3 }; //ok
自定义类也可以有初始化列表,只需要添加一个std::initializer_list构造函数:
class Foo
{
public:
Foo(std::initializer_list<int> list)
{
for (auto i = list.begin(); i != list.end(); ++i)
{
m.push_back(*i);
}
}
public:
std::vector<int> m;
};
Foo foo{ 1,2,3 }; //ok
Foo foo2{ {4,5,6} }; //ok
std::initializer_list的一些细节:
1.它是一个轻量级的容器类型,内部定义了iterator
2.元素的类型必须同种类型
3.它有3个成员函数:size、begin、end
4.它非常高效,内部存储列表中元素的引用
std::initializer_list<int> fun()
{
int a = 1, b = 2;
return{ a,b }; //a,b在返回时并没有拷贝
}
std::initializer_list<int> m = fun();
int s = *m.begin(); //error
初始化列表可以防止收窄
int a{ 1.2 }; //error