Initializer Lists
对于一个类P
class P{
P(int a, int b){
cout << "P(int, int), a=" << a << ", b = " << b << endl;
}
P(initializer_list<int> initlist){
cout << "P(initializer_list<int>), values= ";
for(auto i : initlist)
cout << i << ' ';
cout << endl;
}
}
当运行
//和第一种构造函数完全吻合
P p(77, 5); //P(int a, int b), a = 77, b = 5
//输入参数为一包,和第二种构造函数更加符合
P q{77, 5}; //P(initializer_list<int> initlist), values = 77 5
//输入参数为一包,只能与第二种构造函数吻合
P r{77, 5, 42};//P(initializer_list<int> initlist), values = 77 5 42
//一包参数,和第二种构造函数更加符合
P s = {77, 5}; //P(initializer_list<int> initlist), values = 77 5 42
讨论:如果只有第一种构造函数时,p不受影响,q也不受影响,因为这一包数据会被拆解为2个数据,恰好符合构造函数的参数要求,但是r会被拆解为3个参数,不符合构造函数的要求,s也不影响。
initializer_list
的背后是一个array
,但是实际上array
是一个迭代器。
编译器在看到大括号{}
时就会自动调用initializer_list
的私有构造函数,按理说应该没有人能够调用它的私有构造函数,但是编译器具有最高权限,编译器可以调用。实际过程是:编译器在看到大括号{}
后,在调用私有构造函数之前,就已经准备好了一个array
,然后把这个array
的头部传进来,长度也传进来,将其登记起来。
explicit(用于输入参数多于1个实参(多个参数没有默认值)的构造函数)
拒绝隐式的类型转换,让编译器不要自作聪明,在构造函数前声明,则只有被人为明确调用时才会调用,不允许编译器自己偷偷调用。
对于一个类P
class P{
public:
P(int a, int b){
cout << "P(int a, int b) \n";
}
P(initializer_list<int>){
cout << "initializer_list<int> \n";
}
explicit P(int a, int b, int c){
cout << "explicit P(int a, int b, int c) \n";
}
}
void fp(const P&){};
运行下面的代码
P p1(77, 5); //P(int a, int b)
P p2{77, 5}; //P(initializer_list<int>)
P p3{77, 5, 42}; //P(initializer_list<int>)
P p4 = {77, 5}; //P(initializer_list<int>)
P p5 = (77, 5, 42); //error
p P6(77, 5, 42); //explicit P(int a, int b, int c)
P p7 = {77, 5, 42}; //P(initializer_list<int>)
fp({47, 11}); //P(initializer_list<int>)
fp({47, 11, 3}); //error
fp(P{47, 11}); //P(initializer_list<int>)
fp(P{47, 11, 3}); //P(initializer_list<int>)
p P11{77, 5, 42, 500}; //P(initializer_list<int>)
p P12 = {77, 5, 42, 500}; //P(initializer_list<int>)
p P13{10}; //P(initializer_list<int>)
下面重点解释下为什么P p3{77, 5, 42};
不会报错,但是P p5 = (77, 5, 42);
会报错:
P p3{77, 5, 42};
属于列表构造,你使用花括号{}
初始化时,initializer_list<int>
构造函数会优先被调用,不会再管explicit P(int a, int b, int c)
构造函数,所以不会报错。
但是P p5 = {77, 5, 42};
属于拷贝构造,拷贝构造会隐式调用P(int a, int b, int c)
但是该构造函数前面加了个explicit
,导致没有合适的构造函数可以调用,最终导致报错。