上一篇:《深入理解C++11》笔记–显式转换操作符
本编继续介绍第三章中的内容:列表初始化。
原来C++可以铜鼓花括号{}对数组元素进行统一初始化。例如:
int a[5] = {0};
int b[5] = {1, 2, 3, 4, 5};
但是自定义的类型无法使用这种列表初始化,例如vector就不行,而C++11扩展了对自定义类型列表初始化的支持。
int a[5] = {0}; // C++11支持,C++98支持
int b[] {1, 2, 3, 4, 5}; // C++11支持
std::vector<int> c{1, 2, 3}; // C++11支持
std::map<int, float> d{{1, 1.1}, {2, 2.2},{3, 3.3}}; // C++11支持
那么自定义的类怎么支持列表初始化呢?来看看下面的例子,只要利用std::initializer_list实现初始化列表构造函数就行了。
class Example{
public:
Example(std::initializer_list<int> list)
{
auto i = list.begin();
while(i != list.end())
{
vec.push_back(*i);
++i;
}
}
private:
std::vector<int> vec;
};
int main()
{
Example ex = {1,2,3};
return 0;
}
初始化列表还有一个特点,就是能够防止类型收窄,类型收窄的几种典型的情况:
- float转化成int,double转化成float,丢失精度
- 整形转化成浮点数类型,整形超过了浮点数类型的最大值,丢失数据
- 整形转化成长度较低的整形且无法容纳,int转化成char,丢失数据
C++中是允许这些转化,不过一般编译器会有警告。而列表初始化是不允许这些转化的,这样可以有效的减少一些不注意的错误。
int a = 1.1;
int b{1.1}; // 收窄,无法编译通过
char c{127};
char d{128}; // 超出最大值,无法编译通过