引例
我们在写c++代码的时候,多多少少会遇到这样写的:
如果是这样写还好说:
第一个是因为编译器强制匹配参数。
其他都是因为在有对应构造函数的情况下支持的隐式类型转换。
而支持的构造函数是这个:
如果有不懂的可以开这一篇,通过目录查找隐式类型转换:c++类。
那么写的这一场串的就是另一种类型:initializer_list,即初始值设定项列表
初始值设定项列表(initializer_list)
基础写法
initializer_list<>={ , , , , , , ......};
例如我们要写int类型的:
double类型的:
对应相关函数
其中有成员函数:
和类的使用是相同的。
构造函数
上面已讲
size
主要是返回内部的数据个数
begin、end
由这可以看出,initializer_list是有迭代器的,不知道迭代器的可以看着一篇:c++迭代器讲解
begin是返回迭代器的开始,end是返回迭代器的末尾:
既然支持迭代器,那么范围for同样支持:
全局函数的begin和end
我们看全局的begin就知道,它是调用了内部的begin。end亦是如此:
initializer_list的运用
那么我们知道了这个东西后,有些类的构造函数就能用这个写了:
我们以vector来进行举例:
这里的_start,_finish,_end_of_storage是:
知道这个就可以看了:
这里记得加const,因为一般我们是不会定义一个initializer_list的变量然后传引用的,我们一般传的是这种:
那么这种写法的{4,3},它的返回值是常性的所以防止权限放大,我们必须要加const。
那么我们再看这三个创建出来的vector打印出来的是什么:
我们发现打印成这样了,说明都用了初始化设定项列表构造。但是问什么会先走这个呢?
第一个原因就是编译器偷懒,能走直路就尽量走直路,不会绕弯路去先搞个隐式类型转换再来一次什么拷贝或者赋值。第二就是我查了官方库,看到:
所以综上是initializer_list优先级高。
我们回过头来再看开始的几个构造法:
第一个不是什么寻常的写法,编译器直接匹配最适合的参数进行对应的构造,所以是初始化设定项列表构造。
第二个是走了隐式类型转换,先通过的初始化设定项列表构造出一个常性的vector<int>类,然后作为赋值给b进行构造,所以走了初始化设定项列表构造和赋值构造,但是编译器做了对应的优化,直接用右边的初始化设定项列表来进行对b的构造。
第三个就是传统的初始化设定项列表构造。
我们可以看一看是不是:
我们在初始化设定项列表构造和赋值构造里面都加打印看走了哪些构造:
我们发现确实如此