1. 程式人生 > >C++ Primer Plus(一)

C++ Primer Plus(一)

完整閱讀C++ Primer Plus 

  系統重新學習C++語言部分,記錄重要但易被忽略的,關鍵但易被遺忘的。

 

預備

  1、C++相對於C增加了最關鍵的兩項,面向物件和範型程式設計。

 

處理資料

  2、對於變數明,C++沒有長度限制;同時,以兩個下劃線或一個下劃線和大寫字母開頭的名稱被保留給實現(編譯器及其使用的資源)使用;以一個下劃線開頭的名稱被保留給實現,用作全域性識別符號。

  3、C++11提供一種大括號初始化器,可以用它初始化任何型別。

1 int ham = {24};
2 int ems{7};
3 int roc = {}; // 為0
4 int rhs{};

  4、對於整型字面值,如果第一位為1~9則為十進位制;如果第一位為0,第二位為1~7,則是八進位制;如果前兩位為0x或0X,則為十六進位制。如果希望使用cout輸出八進位制或十六進位制格式的整數,可以使用cout的控制符(這三個控制符都被包含在std名稱空間)。

1 cout << dec << a; // 10進位制,預設的
2 cout << oct << b; // 8進位制
3 cout << hex << c; // 16進位制

  5、cout.put()、cin.get()的用法,可參照C語言中get()與put()的用法。

  6、C++有一種表示特殊字元的機制,他獨立於鍵盤,被稱作通用字元名。通用字元名以\u或\U開頭,前者後面是8個十六進位制位,後者後面則是16個十六進位制位。這些位表示的是ISO10646碼點。

  7、對於寬字元型別wcha_t,cin和cout無法很好的處理,此時應該使用wcin和wcout。

  8、C++11新增了char16_t和char32_t型別,C++11使用字首u表示前者,U表示後者;並與形式為\u00F6和\U0000222B的通用字元名匹配。

1 u'C' u“be good”   U'R' U”dirty rat”

  

複合型別

  9、cin使用空白(空格、製表符、換行符)來確定字串結束的位置,而cin.getline()可以依據換行符來讀取整行,並且可以制定最多讀取字元的數量。

  10、可以使用沒有名稱的結構型別,方法是省略名稱,同時定義一個結構型別和一個這種型別的變數,不常用,可用作臨時變數。

  11、C++允許對一個整數強制型別轉換為一個列舉值,並參與賦值操作;同時可以有多個值相同的列舉值,目前列舉值也可以使用long,long long型別的值。對於較小的值編譯器會使用一個位元組甚至更少的的位元組,對於包含long型別的列舉,會使用4個位元組。

  12、在C中允許給指標直接賦字面值,但C++不允許,必須進行型別轉換。

 

迴圈和關係表示式

  13、字首遞增,字首遞減,解除引用運算子的優先順序相同,以從右往左的方式進行結合;字尾遞增,字尾遞減的優先順序相同,但比字首運算子的優先順序高,以從左往右的方式結合。

  14、 cin.get(ch)和cin.get()的區別。

屬性 cin.get(ch) cin.get()
傳遞輸入字元的方式 賦值給引數ch 將函式返回值賦給ch
用於字元輸入時函式的返回值  istream物件(執行bool轉換後為true)  int型別的字元編碼
到達EOF時函式的返回值   istream物件(執行bool轉換後為false) EOF 

 

函式——C++程式設計模組

  15、如果資料型別本身並不是指標,則可以將const資料或者非const資料的地址賦給指向const的指標,但只能將非const資料的地址賦給非const指標。

 

函式探幽

  16、函式過載後,在呼叫函式時,如果沒有完全相同的引數型別,編譯器會做強制型別轉換進行匹配,但如果有多個可轉換的型別(也就是說有多個過載過的函式),C++將拒絕這種函式呼叫。

  17、函式過載的關鍵是函式的引數列表,也成為特徵標,以下兩個宣告互斥:

1 long gronk(int n, float m);
2 double gronk(int n, float m);

  C++不允許這種方式的過載,返回型別可以不同,但特徵標必須也不同。

  18、對於過載了引用引數的函式,C++將選擇呼叫最匹配的版本,這使得能夠根據引數是左值引用,const型別的左值引用還是右值引用來定製函式的行為。

  19、 函式模板並非函式定義,在使用模板時,編譯器會針對特定的型別生成函式例項,這種例項化方式被稱為隱式例項化。

  20、C++允許顯式例項化,也就是說可以針對特定型別使用模板生成特定的例項。

1 template void Swap<int>(int, int); // 用<>指定型別,在宣告前加template

  它的語義為“使用Swap()模板生成int型別的函式定義”。

  與顯式例項化不同的是,顯式具體化使用下面兩個等價的宣告之一:

1 template<> void Swap<int>(int, int);
2 template<> void Swap(int, int);

  它們的語義是,“不要使用Swap模板來生產函式定義,而應使用專門為int型別顯示地定義的函式定義”。

  21、還可以在程式中建立顯式例項化:

1 template <class T>
2 T Add(T a, T b){ return a + b; }
3 int m = 6;
4 double n = 9.8;
5 cout << Add<double>(m, n) << endl;

  由於這裡顯示例項化中的特定型別為double,所以變數m會被強制型別轉換成double型別。

  22、對於函式過載,函式模板,函式模板過載,C++將選擇哪個版本?

  請看這裡--------->   C++ 函式過載,函式模板和函式模板過載,選擇哪一個?

  23、C++11,在函式模板中,當無法得知一個變數的值時,可以使用decltype關鍵字來決定返回值型別:

1 template<class T1, class T2>
2 void ft(T1 x, T2 y)
3 {
4     decltype(x+y) xpy = x + y; // 此時xpy的型別就是x+y後的型別
5 }

  24、decltype關鍵字本質上更復雜一些,編譯器必須遍歷一個核對錶去確定型別,現在有如下宣告:

1 decltype(expression) var;

  第一,expression是一個沒有用括號括起來的識別符號,則var的型別與該識別符號相同,包括const等限定符。

  第二,如果expression是一個函式呼叫,則於與函式的返回值相同,這裡並不執行函式,只是檢視返回值型別。

  第三,如果expression是一個左值,並且expression是被括號括起的,var會是引用型別,否則第一步就會處理。

  第四,到了這裡,var的型別只能與expression相同。

  25、C++11,在函式模板中,當無法得知返回值型別時,一般不可以直接使用關鍵字decltype來得到返回值型別,因為此時往往decltype後面表示式中的變數還不在作用域內,此時,需要使用後置返回型別。

1 template<class T1, class T2>
2 auto gt(T1 x, T2 y) -> decltype(x+y) // 此時x,y已在作用域內
3 {
4     return x + y;
5 }

  auto表示是一個佔位符,表示後置返回型別提供的類