C Primer閱讀心得(第三章)

2021-04-14 15:20:29 字數 3845 閱讀 6766

1.在標頭檔案(*.h或者*.hpp)中不要使用using語句。因為如果標頭檔案中使用了using語句後,每個include它的原始檔中都預設包含了這個using,那麼可能會與這個原始檔中的變數名或者其他的標頭檔案中的變數名產生衝突。

2.string物件的讀入:過載的》以空格為結束符,而getline以換行符為結束符。

string s;

cin>>s;

cout<

3.c++11中修正了》號在宣告stl物件時的bug。(這bug終於修上了啊~~淚奔)

vector> ivv; //舊版,兩個》之間必須有空格,否則編譯錯誤

vector> ivv; //c++11版,不需要在兩個》之間加入空格

4.列表初始化vector時需要注意編譯器對列表{}中內容的解釋順序:

vectorv1 = ; //ok,列表初始化

vectorv2; //ok,列表初始化

vectorv3; //ok,雖然無法使用10列表初始化,但是還可以呼叫建構函式建立乙個大小為10的string vector

5.注意string物件和vector的size()函式返回的是size_type型別,這是個與機器無關的無符號型別(用int型接著小心溢位...),嫌string::size_type或者vector::size_type寫起來麻煩的可以使用auto或者decltype來偷懶。

6.使用stl的泛型程式設計時應該注意,使用迭代器遍歷乙個序列時,迴圈中判斷是否越界要使用!=,而不要使用《或者》。這是因為所有的標準庫容器都定義了==和!=,而只有少數的容器定義了《和》。

for(auto it = s.begin(); it!=s.end(); it++)

//do sth

7. const_iterator:在容器中,存在乙個const_iterator的迭代器,對這個跌迭代器使用*號(解引用)將返回乙個const物件。也就說使用const_iterator只能唯讀的訪問容器中的資料,但是const_iterator本身可以修改。注意:const物件的begin()和end()會返回const_iterator,而非const物件的begin()和end()只會返回普通iterator。另外,在c++11中,為了使用方便,定義了兩個新的函式cbegin()和cend(),無論物件是否const都返回const_iterator。
string sa = "abc";

const string sb = "def";

auto it1 = sa.begin(); //普通iterator

auto it2 = sb.begin(); //const_iterator

auto it3 = sa.cbegin(); //const_iterator

8.difference_type:我們知道,對容器呼叫size()方法會返回乙個size_type型別的整數,相當於unsigned。在此之外,如果同乙個容器的兩個iterator相減,將返回difference_type型別的整數,相當於signed,嗯,當然也是表示範圍很大的乙個型別。

9.陣列的維數與constexpr:在定義陣列時,陣列的維數要求是編譯器就能確定的大於1的整數。除了整數字面常量及表示式、列舉成員、使用整數字面常量或表示式初始化的const整型物件之外,還可以使用c++11中新定義的constexpr宣告的變數或者函式。

10.宣告陣列時要求有明確的型別,所以不能使用auto來作陣列的型別。陣列的元素應該是物件,所以不允許引用陣列。

11.可以使用空{}列表初始化內建型別陣列為預設值(可以少寫乙個memset了?):

int a[16] = {};        //全是0

double b[16] = {}; //全是0

char c[16] = {}; //全是'\0'

12.指標陣列、指向陣列的指標和指向陣列的引用(不是引用的陣列呦~~)

int *pa[10]; //int *的指標陣列

int (*pa)[10]; //指向有10個元素的陣列的指標

int (&pa)[10]; //指向有10個元素的陣列的引用

//可以按照離變數名的遠近關係依次解讀來搞清楚這些定義:(後續的函式指標也可以同樣解讀)

//例如:int (&pa)[10];

// 1.pa是乙個引用

// 2.pa是乙個有10個元素的int陣列的引用

13.陣列維數和下標的正確型別是size_t。(我一直用int的...omg!)size_t是乙個與機器相關的unsigned整數型別,足以存下陣列所有的下標。

14.陣列頭指標與auto和decltype:我們知道,陣列的名稱會被編譯器自動解析為陣列的頭指標(陣列的第乙個元素的指標)。當使用auto和陣列名時,你會得到指標型別;當使用decltype和陣列名時,你會得到陣列型別(果然auto比decltype多做了一層轉換):

int ia = ;

auto a = ia; //a的型別是int *

decltype(ia) b; //b的型別是int [5]

15.為了指標(陣列)的使用安全與方便,c++11新增了begin()和end()庫函式,它們會產生和stl容器的begin()和end()同樣的行為(乙個指向開頭,另乙個指向末尾元素的下乙個位置):
int ia[2][3] = ;

for(auto p=begin(ia); p!=end(ia); p++)

for(auto q=begin(*p); q!=end(*p); q++)

//do sth

16.兩個指標做差,返回的型別是ptrdiff_t型別,屬於signed,類似type_size和difference_size的關係,正好與size_t組成一對。

17.stl容器的下標要求必須是非負整數,而陣列的下標沒有這一要求,也就是說,你可以使用負數。(我的三觀啊啊啊~~)

int a[10];

int *p = a + 5; //p指向a[6]

int k = p[-2]; //k = a[4]

18.c++語言中沒有多維陣列,只有陣列的陣列。
int ia[3][4]; //ia是乙個大小為3的陣列,其中每個元素都是大小為4的int型陣列
19.範圍for與多維陣列:通常我們使用下標和多重迴圈遍歷多維陣列,但是當我們使用c++11中新增加的範圍for的時候,必須宣告每一層迴圈時的物件型別。通過第14項我們可以知道,使用auto時陣列名會被自動解析為指標型別,這會導致內層迴圈無法進行下去(指標不是序列,無法應用範圍for)。這時我們需要將除了最內層迴圈之外的每一層迴圈的物件型別宣告為auto &,就可以避免陣列名會被自動解析為指標型別,讓內層迴圈正確執行。
int matrix[2][3] = ;

for (auto row : matrix)

for (auto element : row) //編譯錯誤,row是指標無法範圍for

//do sth

//改為:

for (auto &row : matrix)

for (auto element : row) //ok,row是int [3]

//do sth

20.多維陣列的陣列名會被轉化為第一層陣列首元素的指標(這是15和19加在一起的推論),我們可以使用auto來簡化它:
int ia[2][3][4];

int (*p)[3][4] = ia; //轉化首元素指標

auto *p = ia; //方便了,但是容易記不清型別

c primer 第三章閱讀筆記

3.1 標頭檔案不應包含using宣告 3.2 string p75 表示可變長的字串行 等號初始化叫做拷貝初始化 不使用 則執行的是直接初始化 用多個值進行初始化 string 物件會自動忽略開頭的空白 空格,換行,製表等 並從乙個真正的字元開始讀起,直到遇見下處空白 getline 引數是乙個輸...

C primer 第三章備忘。

1 處理每個字元?使用基於範圍的for語句 for declaration expression statement 其中expression部分是乙個物件,表示乙個序列 declaration部分負責定義乙個變數,用以訪問序列中的基礎元素 例子 string str some string for...

c primer 筆記,第三章

初始化string物件的6種方式 string s1 預設空串 sting s2 s1 string s2 s1 string s3 value 直接初始化 string s3 value 拷貝初始化 string s4 n,c 由連續n個字元c組成的串在讀寫string物件時,string物件會自...