第四章 複合類型
影響最深的複合類型是類,它是將學習的OOP的堡壘。複合類型必將是用來處理更加複雜的資料類型。
C++沒有數組越界的檢測
越界的代碼可能能夠正確運行和結束,但是也可能因為越界整個程式乃至作業系統崩潰。C++的數組其實和指標有著緊密的聯絡,和使用指標訪問可能就是一個形式上的不同,本質上沒有任何區別。也即a[7]與*(a+7)在編譯器看來是等價的。
字串常量
C++中能夠定義字串常量,但是如果一個字元指標是使用字串指標來初始化的,那麼這個指標是不能夠用來改變這個常量的。且如果定義了兩個相同的常量那麼不同的系統可能採用不同的策略來決定是只保留一份還是多份。
幾個函數
getline()接受一行,並丟棄換行,get()接受一行但是不丟棄斷行符號,並將斷行符號留在輸入緩衝區內,如果一直使用get()來讀取一行的話,將沒有將這個斷行符號處理掉,需要使用一個get()的一個重載函數來讀掉最後的一個斷行符號。
匿名結構體/共用體
所謂匿名就是在定義一個結構體或者是共用體的時候不給定這個類型的名字,而是一次性使用。在定義一個結構體的時候,可以將一個匿名共用體直接當做一個結構體的成員變數,而不需要在結構體外先聲明這個共用體。
指標與變數
變數是將值視為給定的量,而將地址視為派生量,指標將地址視為給定的量,而將值視為派生量。個人更喜歡吧“*”稱作解除引用運算子。
一定要在對指標應用解除引用(*)之前,將指標初始化為一個確定的、適當的地址。
指標的算術運算
指標的算術運算上加1是加上基本類型所佔用記憶體大小個單元。int a[5]其中a的基本類型是int *,因此a+1地址加4,而&a 的基本類型是int (*)[5],&a+1地址加20。
C++的記憶體管理方法
C++有三種管理資料記憶體的方式:自動儲存、靜態儲存和動態儲存裝置。
自動儲存:
在函數內部定義的常規變數使用自動儲存空間,被稱為自動變數,隨著函數的調用出現,隨著函數的消失而消亡。是一種棧的儲存結構。
靜態儲存:
一個變數要成為靜態變數的方式有兩種:一種是在函數外面定義了它,而另外一種是在聲明變數時使用關鍵字static。
動態儲存裝置:
New和delete運算子提供了一種比自動變數和靜態變數更靈活的方法。他們管理了一個記憶體池,這個在C++中被稱為自由儲存空間或堆。
數組的替代品:
vector以及array能夠用來替代數組,並且用過.at()的成員變數來檢測數組是否越界。
第五章 迴圈和關聯運算式
自增/自減運算子&副作用和順序點:
副作用是指在計算運算式時對某些東西(如儲存在變數中的值)進行了修改。C++中語句中的分號就是一個順序點,一個完整的運算式的末尾也是一個順序點。一個完成的表示式是指一個運算式不是另外一個更大的運算式的子運算式。C++只能夠確保當到達一個順序點時,賦值運算子、遞增、遞減運算子執行的所有修改都要完成。
y = (4 + x++) + (6 + x++);
運算式4 + x++不是一個完整的運算式,因此C++不保證x的值在計運算元運算式4 + x++後立即增加1。在這個例子中,整個指派陳述式是一個完整運算式,而分號標示了順序點,因此C++只保證程式執行到下一條語句之前,x的值將被遞增兩次。C++沒有規定是在計算每個子運算式之後將x值遞增,還是整個運算式計算完畢後才將x的值遞增,有鑒於此,我們應該避免使用這樣的運算式。
對於系統變數而言在沒有使用一個變數時,藉助於智能的編譯器自增自減效果一樣。但是我們在使用自己的類時,首碼運算子要更好,因為後者要開闢一個臨時的空間。
迴圈的邊界
對於迴圈的邊界一定要處理好,尤其在一些“好”的迴圈下(到達邊界後還是沒有因為非法而退出),因此一些硬性的規定或者是哨兵位是我們要選擇的。
for,while ,do...while
for迴圈主要用來處理那些已知次數的迴圈,而後兩者用來處理迴圈次數未知的迴圈。前兩者又稱為允入準則迴圈,後者又稱為出口條件迴圈。
類型別名:
C++有兩種定義類型別名的方式:#define 和 typedef,推薦後者是因為在以下的情況下define會有一定的問題。
#define int* pword
pword p1, p2;
我們的本意可能是要定義兩個指向int類型的指標,但是p2確實一個int型。typedef就能夠避免這樣的問題。
數組的遍曆:
C++11增加了兩種對數組的遍曆。
int a[5] = {1, 2, 3, 4, 5};
for (int x : a) {...} 這樣就能夠通過x來訪問各個元素,如果要更改各個元素的話
for (int &x : a) {...} 採用左邊的引用格式。