完整閱讀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表示是一個佔位符,表示後置返回型別提供的型別。