C++使用initializer_list
1.vector的列表初始化
我们知道vector类型可以这样初始化:
vector<int> v1 = { 1, 2 , 3 };
这样初始化比较方便。之前在写一些数据结构的时候,想要连续插入一些值,总是要多次使用诸如insert或push_back的操作,十分复杂。于是在想,标准库里这些容器是怎样实现用一个大括号列表来初始化的呢?如果我们在VS里写一行这样的代码:
auto x = { 1, 2 ,3 };
把鼠标移至x上,编译器帮我们显示出了x的类型:std::initializer_list<int>
所以,我们可以在类中写一个构造函数,并且它接受的类型为std::initializer_list<T>
在此之前,先了解一下这个类型。
2.initilizer_list简介
- 这是C++提供的一种模板类型,以下代码这样声明并初始化了一个对象
lst1
initializer_list<int> lst1 = { 1, 2 ,3 };
- 用
lst1
来初始化lst2
的时候,他们两个共享同一块内存,也就是说不会进行复制。比如,以下代码打印出两个lst的begin()
迭代器指向同一个地址:
initializer_list<int> lst2 = lst1;
cout << &(*lst1.begin()) << endl << &(*lst2.begin()) << endl;
- 构造对象lst1后,不能对其中的值进行修改,但是可以让它指向另一块内存
- lst1可使用的方法有:begin(), end(), 以及size()
3.定义使用initializer_list的类
现在,定义一个简单的类MyArray
,并且在它的构造函数里使用初始化列表:
class MyArray
{
private:
int* arr;
static const int SIZE = 100; //假定不会超过此范围
public:
int len = 0;
MyArray(initializer_list<int> iList)
{
arr = new int[SIZE];
for (auto it = iList.begin(); it != iList.end(); it++)
{
int index = (int)(it - iList.begin());
arr[index] = *it;
}
len = iList.size();
}
void print()
{
for (int i = 0; i < len; i++)
cout << arr[i] << " ";
}
}; //MyArray
经此定义后,我们便可以这样初始化MyArray:
MyArray arr = {1, 2, 3};
arr.print(); //输出为1 2 3
还需注意的是,使用初始化列表的时候不允许发生“丢失精度的类型转换”。比如arr接受int类型的变量来初始化,如果有以下两种写法:
short x = 3;
long long y = 3;
MyArray ar1 = {1, 2, x}; //允许
MyArray ar2 = {1. 2. y}; //错误
第三行是允许的,而第四行编译器会提示错误信息:从 “long long” 到 “int” 进行收缩转换无效。