国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

需要可變參數的時候,為什么不用vector代替initializer_list?

2019-11-08 18:40:01
字體:
來源:轉載
供稿:網友

在重載的時候,vector會有問題。

當需要可變參數,如果使用vector的話,可能會遇到下面這個問題。函數f有兩個重載的版本,編譯器無法選擇具體調用vector還是list的版本。

void f(std::vector<int> const &items){};void f(std::list<int> const &items){};f({ 1, 2, 3, 4 }); //ambiguous call to overloaded function

而使用initializer_list的話,就不會出現錯誤了。編譯器優先匹配了initializer_list的版本。

void g(std::vector<int> const &items){};void g(std::list<int> const &items){};void g(std::initializer_list<int> const &items){};g({ 1, 2, 3, 4 }); // no error

initializer_list不能修改,更符合參數的特點。

vector有push_back函數,也就是說vector可以在函數里面修改,所以必然vector必須在heap上分配空間來存儲數據。而initializer_list只有beginend函數,函數內并不能修改它,所以編譯器有機會在stack上存儲initializer_list的數據來提高性能。

initializer_list has pointer semantics while the vector has value semantics.

vector是值語義,也就是說拷貝一個vector,那里面的元素也會被拷貝一次。而initializer_list是指針語義,里面的元素并不會被拷貝。比如說下面這段代碼listlist2begin其實指向了同一個空間。這樣的設計是合理的,因為initializer_list是不可修改的,沒有理由再拷貝一次。

std::initializer_list<int> list = { 1, 2, 3, 4 }; std::initializer_list<int> list2; list2 = list; std::cout << list2.begin() << std::endl; std::cout << list.begin() << std::endl;

指針語義的好處是,下面這段遞歸函數不會對里面的元素產生很多次復制。雖然每次都構造了一個新的initializer_list,但是里面的數值{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }并沒有經過復制。

int sum(std::initializer_list<int> const &items){ std::cout << items.begin() << std::endl; if (items.begin() == items.end()){ return 0; } std::initializer_list<int> next(items.begin() + 1, items.end()); return *(items.begin()) + sum(next);};std::cout << sum({ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });

initializer_list 背后的設計思想。

在C++11的時候,大家都想加上一個值列表的東西,就像{ value1, value2, value2... valueN }一樣。一種想法是搞出一個新的關鍵字,給C++增加一個新的build-in類型。但是新的關鍵字很有可能會導致老的程序無法被編譯,如果湊巧老的程序使用了那個關鍵字做名字。于是C++11的做法是,只是在標準模板庫里面增加一個新的模板initializer_list,然后讓編譯器遇到{1,2,3,4}這種東西的時候,隱式的轉換成一個initializer_list的對象。下面這段代碼輸出的是class std::initializer_list<int>

auto list = { 1, 2, 3 }; std::cout << typeid(decltype(list)).name() << std::endl;

有了這個基本的東西以后,剩下的問題就可以在已有的框架里面解決了。比如說實現std::vector<int> v = { 1, 2, 3 };這個功能。其實就是編譯器遇到{ 1, 2, 3 }就生成了一個initializer_list,然后調用了vector對應的一個構造函數.

vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );

回到最初的fg的例子,g({ 1, 2, 3, 4 });沒有編譯錯誤,因為有一個最佳的匹配。f({ 1, 2, 3, 4 });出現了編譯錯誤,因為沒有最佳的一個匹配,編譯器面臨著隱式類型轉換,但是有兩個選擇,vector和list,所以就有編譯錯誤了。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 禹城市| 吉林市| 丹江口市| 桂阳县| 马尔康县| 红桥区| 客服| 苏尼特左旗| 英山县| 延长县| 西宁市| 石狮市| 邵武市| 交口县| 临高县| 健康| 刚察县| 香港| 怀仁县| 西藏| 汝州市| 扬中市| 綦江县| 吉安县| 天峻县| 正镶白旗| 惠东县| 正宁县| 博湖县| 石首市| 大方县| 韶关市| 化隆| 上栗县| 娄烦县| 田东县| 阿城市| 思茅市| 雷山县| 万源市| 眉山市|