標籤:google 前言 strong 學習 使用 曆史 iostream pos 結構
一、前言
C++的學習中。我想每一個人都被變數定義和申明折磨過,比方我在大學筆試過的幾家公司。都考察了const和變數,類型的不同排列組合,讓你差別有啥不同。反正在學習C++過程中已經被折磨慣了,今天再來看看重溫下那段“輝煌的曆史”。先來看一段代碼:
Player pa; // (a) Player pb(); // (b) Player pc = Player(); // (c) Player pd(Player()); // (d) pd = Player() // (e)
a,c,d 都是申明一個變數,a 非常easy理解就是申明一個變數,b第一感覺是調用建構函式來申明變數。事實上不是,而是申明一個無參數,返回Player的函數。
對於c以為是調用了operator= 賦值運算吧?全然不是。而是先產生一個對象。然後調用Player的拷貝建構函式,產生對象pc。d和c是一樣的。e才是真正調用賦值操作。是不是已經被這各式各樣的對象申明搞的暈頭專向了。如今C++11初始化列表正式登場。
二、簡單介紹
在看C++11初始化前,先來回顧一下C語言中的結構體初始化。代碼例如以下:
#include <iostream>struct Player{ int id; const char* name;};int main() { Player player = {10001, "c++"}; printf("%d, %s\n", player.id, player.name);}
結構體變數能夠列表初始化,非常方便。
C++11引入了初始化列表來初始設定變數和對象。
三、怎樣使用
1、系統內建類型
int ia{1}; // (a) int ib = {1}; // (b) int ic(1); // (c) int id = 1; // (d)
非常明顯。還是d 更符合習慣。
std::vector<int> va{1, 2, 3}; // (a) std::vector<int> vb = {1, 2, 3}; // (b) std::vector<int> vc(1, 10); // (c) std::vector<int> vd{1, 10}; // (d)
通過初始化列表能夠彌補c中僅僅能初始化同樣數位問題。在使用中c和d不要混淆了。
std::pair<int, const char*> getPlayer() { return {10001, "c++"}; } std::map<int, const char*> players = {{10001, "c++"}, {10002, "java”}};
還能夠返回pair類型。初始化map都是能夠的。
2、自己定義類型
對於單個參數初始化,類型匹配建構函式,不須要自己定義建構函式。
Player pa{}; // (a) Player pb; // (b) Player pc(); // (c) Player pd(b); // (d) Player pe = b; // (e) Player pf = {b}; // (f)
對於上面幾種變數初始化,推薦a, 假設是帶參數的建構函式,推薦b,若果是不帶參數的建構函式。
3、假設是自己想實現初始化列表建構函式。拷貝函數,賦值函數,須要包括initializer_list 這個標頭檔。
class MyClass{public: MyClass(int a):a_(a){ std::cout << "normal initializer list\n"; } MyClass(std::initializer_list<int> a):b_(a) { std::cout << "initializer list constructor\n"; } MyClass(MyClass& my) { std::cout << "copy constructor\n"; this->a_ = my.a_; this->b_ = my.b_; } MyClass& operator=(MyClass& my) { std::cout << "operator = constructor\n"; this->a_ = my.a_; this->b_ = my.b_; return *this; }private: int a_; std::initializer_list<int> b_;};
這是自己定義類,帶有初始化列表建構函式的類,以下來練習下學過的類相關C++知識:
MyClass ma{1}; // (a) MyClass mb = {1, 2, 3}; // (b) MyClass mc(2); // (c) MyClass md = b; // (d) MyClass me(c); // (e) MyClass mf{e}; // (f) auto l{2, 2, 3,3}; MyClass mh{l}; // (e) ma = mb; // (h)
看一下每次調用都輸出什麼結果,答案在這裡:
initializer list constructor
initializer list constructor
normal constructor list
copy constructor
copy constructor
copy constructor
initializer list constructor
operator = constructor
四、為啥須要初始化列表
1、避免類申明對象混淆,區分對待,對於C++為啥有小括弧初始化對象這一說,大家能夠自行google。看來無論是誰都有犯錯誤的時候。勇於承認錯誤還是好同志。
2、在初始化多個變數時方便
3、避免資料分割,由於通過初始化列表是不同意隱式轉換的,相關知識能夠參考我的
這篇文章。
五、注意事項
1、在申明變數的時候,少用小括弧,程式可讀性更高
2、使用初始化列表防止隱式轉換,降低bug
3、通過 {} 返回的對象是const類型,不可轉換
c++11之初始化列表