《C++ Primer》读书笔记 第三章
1.注意:頭文件不應包含using聲明。因為頭文件的內容會拷貝到所有引用他的文件中去,對于某些程序來說,由于不經意間包含了一些名字,可能會產生名字沖突。
2.string類型的讀入:用cin讀入string,忽略所有的前置空格、換行符、tab等,讀入串,在此讀到這些特殊字符時結束,讀入的串中不包含這些特殊字符。getline讀入時,一直到換行符結束。
3.auto len = line.size();此時len的類型是string::size_type,size()函數返回一個無符號整形數,因此size_type是一種無符號整數類型,也可顯式調用string::size_type a = 0;切記,在調用size()函數時最好不要用int類型,如果在表達式中混用了帶符號類型數和無符號類型數有可能會產生意想不到的結果。
4.字面值和string對象相加:當“+”運算符兩端至少有一個是string對象時,字符字面值會自動轉換成string對象,但兩個都是字符字面值時不可以:string s1 = s + "hehe";//正確string s2 = "he" + "he";//不正確 特殊的string s3 = s + "he" + "he";//正確,因為先計算前兩個得到一個string對象,在與第三個計算。
5.使用頭文件cname和name.h也有不一樣的地方,在名為cname的頭文件中定義的名字從屬命名空間std,而定義在名為.h的頭文件中則不然,因此建議使用cname的形式。
6.注意:string和vector []接收下標的類型是string::size_type和vector::size_type,而不是int,帶符號整數可以當作下標時會自動轉換成size_type類型。
7.特殊的,定義const string s = "hehehehe"; for (auto& c: s) {} //此時c是const char&類型。
8.C++11的新特性,在C++11中,定義嵌套模版類對象時,兩個'>'之間不用再加空格了,要知道在以前的C++版本中是要加空格的。
9.vector:在范圍for循環內不能改變其所遍歷序列的大小,更不能添加元素,但在非范圍的for循環中可以。
10.vector初始化:可以使用花括號或圓括號,如果用圓括號,可以說提供的值是用來構造vector對象的,如果用的是花括號,可以表述稱列表初始化,花括號中的元素一般作為元素初始值的列表來處理。另一方面,如果初始化時使用了花括號的形式但是提供的值又不能用來列表初始化,就要考慮用這樣的值來構造vector對象了,例如:vector<string> v1{10};//有10個默認初始化的元素。vector<string> v2{10,"hehe"};//有10個值為"hehe"的元素
11.vector一種特殊的賦值方式:vector<int> v; v = {1,2,3};//用列表中的元素代替v中的元素。
12.迭代器一般有兩種:iterator和const_iterator,后者為常量迭代器,只能讀不能寫,如果對象是個常量,則只能用iterator,如果是個變量,即能用iterator又能用const_iterator,只不過后者不能寫。
13.容器中的begin和end。begin和end的返回的具體類型由對象是否是常量決定,如果對象是常量,則返回const_iterator,否則返回iterator。為了專門得到const_iterator,C++11新標準引入了兩個新函數:cbegin和cend。不論vector對象(或string對象)本身是否是常量,返回值都是const_iterator;
14.任何一種可能改變vector對象容量的操作,比如push_back,都會使該vector對象的迭代器失效。
15.兩迭代器的差的類型是名為difference_type的帶符號型整數,string和vector都定義了difference_type,因為這個差可正可負,所以是帶符號類型的。
16.數組的維度必須是一個常量表達式。另外,定義數組的時候必須指定數組的類別,不允許用auto關鍵字由初始值的列表推斷類型。數組的初始化這里不多說(詳見P102,英文版P114)
17.定義數組的指針 int (*p)[10];定義數組的引用 int (&a)[10];特別的int* (&b)[10];b是一個引用,指向一個數組,數組里放了10個指針。
18.在使用數組下標時,通常將其定義為size_t類型,size_t是一機器相關的無符號類型,它被設計的足夠大以便能表示內存中任意對象的大小,在cstddef頭文件中定義了size_t類型。
19.在函數內定義int a[10];此時數組未初始化,若定義成int a[10]={};則被默認初始化。
20.當使用數組作為一個auto變量的初始值時,推斷得到的類型是指針而非數組,但當使用decltype函數時,該函數的返回類型是由10個整數構成的數組。
21.C++11中引入了begin和end函數,也支持數組類型,與容器中的begin和end不同,這兩個函數不是成員函數,這兩個函數定義在iterator頭文件中。
22.這里值得一提的是,若定義一個數組,int a[10]; &a和a的區別是:&a和a都是地址,而且值也相同,但類型不一樣,&a是整個數組的地址,而a是數組首元素的地址,因此a與整形指針相容,&a與數組指針相容,&a+1與&a的距離是一個數組的字節數,多維數組也是這樣。
23.如果在表達式中含有解引用運算符和點運算符,在必要的地方加上圓括號。 如:(*it).end();
24.如果用整形指針,下標可以為負數,如int a[10]; int *p = a + 2; p[-2] = 1; 雖然標準庫類型string和vector也能執行下標運算,但是數組與他們相比還是有所不同,標準庫類型限定使用的下標必須是無符號類型,而內置的下標無此要求,內置的下標運算符可以處理負值。
25.在string對象的復合賦值運算中允許使用以空字符結束的字符數組作為右側的運算對象。
26.若要將string對象的內容賦給一個char*字符串,可以調用string函數c_str(),該函數返回一個字符指針,指向這個string對象的內容,為了確保我們不改變這個字符數組的內容,返回結果為const char*。另外,我們無法保證c_str()函數返回的數組一定有效,事實上,如果后續的操作改變了s的值就可能讓之前返回的數組失去效用。
27.vector允許使用數組來初始化vector對象,只需指明要拷貝區域的首元素地址和尾后元素地址就可以了。例如:int a[] = {1,2,3,4,5}; vector<int> v(begin(a),end(a));
28.在多維數組中,如果僅僅想初始化每一行的第一個元素,通過如下的語句即可:int a[3][4]={{0},{3},{4}};
29.使用范圍for循環處理多維數組:int a[10][10]; for (auto& row : a) for (auto& col : row) {col=1;},為什么要用引用類型,這里不單單是改變數組元素的緣故,假設寫成如下形式:for (auto row : a) for (auto cal : row) {}程序無法通過編譯,應該寫成如下形式:for (const auto& row : a) for (auto col : row) {} 盡管這個循環中并沒有任何寫操作,可是我們還是將外層循環的控制變量聲明成了引用類型,這是為了避免數組被自動轉成指針,像之前一樣的第一個循環便利a的所有元素,注意程序元素實際上是大小為4的數組,因為row不是引用類型,所以編譯器初始化row時會自動將這些數組形式的元素轉換成指向該數組內首元素的指針,這樣得到的row的類型就是int*,顯然內層的循環就不合法了,編譯器將試圖在一個int*內遍歷,這顯然和程序的初衷相去甚遠。因此,要使用范圍for語句處理多維數組,除了最內層的循環外,其他所以的循環的控制變量都應該是引用類型。
轉載于:https://www.cnblogs.com/Chierush/p/3454990.html
總結
以上是生活随笔為你收集整理的《C++ Primer》读书笔记 第三章的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [wikioi]多源最短路
- 下一篇: 如何通过VC的 CHttpFile 抓取