普通建構式VS初始化串列建構式
初始化串列建構式最優先匹配問題
對于一個類而言,只要其中包含有初始化串列的建構式,編譯器在編譯使用{}語法的構造時會最傾向于呼叫初始化串列建構式,哪怕做型別轉換也在所不惜,哪怕有型別最佳匹配的普通建構式或移動建構式也會被劫持
class Widget {
public:
Widget(int i, bool b);
Widget(int i, double d);
Widget(std::initializer_list<long double> il);
operator float() const;
};
Widget w1(10, true); // 使?小括號初始化
//調?第?個建構式
Widget w2{10, true}; // 使?花括號初始化
// 調?第三個建構式
// (10 和 true 轉化為long double)
Widget w3(10, 5.0); // 使?小括號初始化
// 調?第二個建構式
Widget w4{10, 5.0}; // 使?花括號初始化
// 調?第三個建構式
// (10 和 5.0 轉化為long double)
Widget w5(w4); // 使?小括號,調?拷?建構式
Widget w6{w4}; // 使?花括號,調?std::initializer_list建構式
Widget w7(std::move(w4)); // 使?小括號,調?移動建構式
Widget w8{std::move(w4)}; // 使?花括號,調?std::initializer_list建構式
編譯器這種熱衷于把括號初始化與初始化串列建構式匹配的行為,會導致一些莫名其妙的錯誤
class Widget {
public:
Widget(int i, bool b);
Widget(int i, double d);
Widget(std::initializer_list<bool> il); // element type is now bool
… // no implicit conversion funcs
};
Widget w{10, 5.0}; //錯誤!要求變窄轉換,int(10)double(5.0)無法轉換為bool型別
只有在沒有辦法把{}中實參的型別轉化為初始化串列時,編譯器才會回到正常的函式決議流程中
?如我們在建構式中?std::initializer_list<std::string>代替std::initializer_list<bool> ,這時?std::initializer_list建構式將再次成為函式決議的候選者,因為沒有辦法把int和bool轉換為std::string:
class Widget {
public:
Widget(int i, bool b);
Widget(int i, double d);
Widget(std::initializer_list<std::string> il);
…
};
Widget w1(10, true); // 使?小括號初始化,調?第?個建構式
Widget w2{10, true}; // 使?花括號初始化,調?第?個建構式
Widget w3(10, 5.0); // 使?小括號初始化,調?第?個建構式
Widget w4{10, 5.0}; // 使?花括號初始化,調?第?個建構式
{}空初始化串列會發生什么
假如{}內是空的,類中既有默認建構式,也有初始化串列建構式,此時{}會被視為沒有實參,而不是一個空的初始化串列,因此會呼叫默認建構式,如果就是想呼叫初始化串列建構式,這應該使用{{}}的方式
class Widget {
public:
Widget();
Widget(std::initializer_list<int> il);
...
};
Widget w1; // 調?默認建構式
Widget w2{}; // 同上
Widget w3(); // 最令?頭疼的決議!宣告?個函式
Widget w4({}); // 調?std::initializer_list
Widget w5{{}}; // 同上
初始化串列帶來的vector的坑
std::vector<int> v1(10, 20); //使??std::initializer_list
//建構式創建?個包含10個元素的std::vector
//所有的元素的值都是20
std::vector<int> v2{10, 20}; //使?std::initializer_list
//建構式創建包含兩個元素的std::vector
//元素的值為10和20
初始化串列建構式問題帶來的兩點啟示
- 作為類別庫作者,如果在建構式中多載了一個或多個初始化串列建構式,要考慮用戶使用{}初始化的情況,最好避免類似std::vector中的情況,應該盡可能做到用戶無論用小括號還是花括號進行初始化都不會產生區別,一定要慎重考慮新出現的初始化串列建構式對其他建構式的影響!!!
- 作為類別庫使用者,必須認真的考慮小括號和花括號之間選擇創建物件的方式,最好選擇其中一個從一而終
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/552496.html
標籤:其他
上一篇:AccessToken、for_user、get_token
下一篇:返回列表
