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
,導致沒有合適的構造函數可以調用,最終導致報錯。