表示式由乙個或多個運算元通過操作符組合而成。最簡單的表示式僅包含乙個字面值常量或變數。較複雜的表示式則由操作符以及乙個或多個運算元構成。
每個表示式都會產生乙個結果。如果表示式中沒有操作符,則其結果就是運算元本身的值。當乙個物件用在需要使用其值的地方,則計算該物件的值。
操作符的含義——該操作符執行什麼操作以及操作結果的型別——取決於運算元的型別。
c++提供了一元操作符和二元操作符兩種操作符。作用在乙個運算元上的操作符稱為一元操作符。如曲位址符(&)和解引用操作符(*);而二元操作符則作用於兩個運算元上,如加法操作符(+)和減法操作符(-)。
一、算術操作符
當只有乙個運算元為負數時,求模操作結果值的符號可依據分子(被除數)或分母(除數)的符號而定。如果求模的結果隨分子的符號,則除出來的值想零一側取整;如果求模與分母的的符號匹配,則除出來的值向負無窮一側取整。
二、關係操作符和邏輯操作符
關係操作符和邏輯操作符
操作符功能
!邏輯非
<
<=
>
>=
小於小於等於
大於大於等於
==!=
等於不等
&&邏輯與
||邏輯或
2.1 邏輯與、邏輯或操作符
僅當邏輯與(&&)操作符的兩個運算元都為true,其結果才得true。
對於邏輯或(||)操作符,只要兩個運算元之一為true,它的值就為true。
注:邏輯與和邏輯或操作符總是先計算做運算元,然後再計算其右運算元。只有在僅靠左運算元的值無法確定該邏輯表示式的結果時,才會求解其右運算元。我們常常稱這種求值策略為「短路求值」。
2.2 不應該串接使用關係操作符
三、位操作符
位操作符使用整型的運算元。位操作符將其整型運算元視為二進位制位的集合,為每一位提供檢驗和設定的功能。
位操作符
操作符功能
~位求反
<<
>>
左移右移&位與
^位異或|位或
位操作符操縱的整數的型別可以是有符號的也可以是無符號的。如果 運算元為負數,則位操作符如何處理其運算元的符號位依賴於機器。於是它們的應用可能不同:在乙個應用環境中實現的程式可能無法用於另外一應用環境。
對於位操作符,由於系統不確保如何處理其運算元的符號位,所以強烈建議使用unsigned整型運算元。
左移操作符(<<)在右邊插入0以補充空位。對於右移操作符(>>),如果其運算元是無符號位,則從左邊開始插入0;如果運算元是有符號位,則插入符號位的副本或者0值,如何選擇需依據具體的實現而定。移位操作的右運算元不可以是負數,而且必須是嚴格小於左運算元位數的值。否則,操作的效果未定義。
3.1 bitset物件或整型值的使用
3.2 將移位操作符用於io
四、 賦值操作符
複製運算元的左運算元必須是非const的左值。
五、自增和自減操作符
六、sizeof操作符
sizeof操作符的作用是返回乙個物件或型別名的長度,返回值的型別為size_t,長度的單位是位元組。sizeof表示式的結果時編譯時常量,該操作符有以下三種語法形式:
sizeof(type name);
sizeof ( expr);
sizeof expr;
將sizeof應用在表示式expr上,將獲得該表示式的結果的型別長度。
將sizeof用於expr時,並沒有計算表示式expr的值。特別是在sizeof *p中,指標p可以持有乙個無效位址,因為不需要對p做解引用操作。
使用sizeof的結果部分地依賴所涉及的型別:
1、對char型別或值為char型別的的表示式做sizeof操作保證得1;
2、對引用型別做sizeof操作將返回存放此引用型別物件所需的記憶體空間的大小。
3、對指標做sizeof操作將返回存放指標所需的記憶體的大小;注意,如果要獲取該指標所指向物件的大小,則必須對該指標進行解引用。
4、對陣列做sizeof操作等效於將對其元素型別做sizeof操作的結果乘上陣列元素的個數。
七、new和delete表示式
定義變數時,必須指定其資料型別和名字。而動態建立物件時,只需要指定其資料型別,而不必為該物件命名。取而代之的是,new表示式返回指向新建立物件的指標,我們通過該指標來訪問此物件。
7.1 動態建立物件的初始化
動態建立物件可用初始化變數的方式實現初始化:
int i(1024);
int *pi = new int(1024);
string s(10, '9');
string *ps = new string(10. '9');
c++使用直接初始化語法規則初始化動態建立的物件。如果提供了初值,new表示式分配到所需要的記憶體後,用給定的初值初始化該記憶體空間。
7.2 動態建立物件的預設初始化
如果不提供顯示初始化,動態建立的物件與函式內定義的變數初始化方式相同。對於類型別的物件,用該類的預設建構函式初始化;而內建型別的物件則無初始化。
7.3 耗盡記憶體
如果new表示式無法獲取需要的記憶體空間,系統將拋出名為bad_alloc的異常。
7.4 撤銷動態建立的物件
動態建立的物件用完後,程式設計師必須顯示地將該物件占用的記憶體返回給自由儲存區。c++提供了delete表示式釋放指標所指向的位址空間。
7.5 零值指標的刪除
如果指標的值為0.則在其上做delete操作是合法的,但這樣沒有任何意義:
int *ip = 0;
delete ip;
c++保證:刪除0值的指標是安全的。
7.6 在delete之後,重設指標的值
刪除指標後,該指標變成懸垂指標。懸垂指標指向曾經存放物件的記憶體,但該物件已經不再存在了。懸垂指標往往導致程式錯誤,而且很難檢測出來。
一旦刪除了指標所指向的物件,立即將指標置為0,這樣就非常清楚地表明指標不再指向任何物件。
7.7 const物件的動態分配和**
const int *pci = new const int(1024);
與其他常量一樣,動態建立const物件必須在建立時初始化,並且一經初始化,其值就不能在修改。
警告:動態記憶體的管理容易出錯
下面三種常見的程式錯誤都與動態記憶體分配相關:
(1)、刪除(delete)指向動態分配記憶體的指標失敗,因而無法將該塊記憶體返還給自由儲存區。刪除動態分配記憶體失敗稱為「記憶體洩漏(memory leak)」。記憶體洩漏很難發現,一般需等應用程式執行了一段時間後,耗盡了所有的記憶體空間,記憶體洩漏才會顯露出來。
(2)、讀寫已刪除的物件。如果刪除指標所指向的物件之後,將指標置為0值,則比較容易檢測出這類錯誤。
(3)、對同乙個記憶體空間使用兩次delete表示式。當兩個指標指向同乙個動態建立的物件,刪除時就會發生錯誤。如果在其中乙個指標上做delete運算,將該物件的記憶體空間返還非自由儲存區,然後接著delete第二個指標,此時則自由儲存區可能會被破壞。
7.8 刪除const物件
delete pci;
即使delete表示式的運算元是指向int型const物件的指標,該語句同樣有效**pci所指向的內容。
八、型別轉換
表示式是否合法取決於運算元的型別,而且合法的表示式其含義也是由運算元型別決定。
如果這兩個型別之間可以相互轉換,則稱這兩個型別相關。
c++並不是把兩個不同型別的值直接加在一起,而是提供了一組轉換規則,以便在執行算術操作之前,將兩個運算元轉換為同一種資料型別。這些轉換規則由編譯器自動執行,無需程式設計師介入。因此,他們也被稱為隱式型別轉換。
8.1 何時發生隱式型別轉換
編譯器在必要時將型別轉換規則應用到內建型別和類型別的物件上。在下列 情況下,將發生隱式型別轉換:
1、在混合型別表示式中,其運算元被轉換為相同的型別:
int ival;
double dval;
ival >= dval;//ival converted to double
2、用作條件的表示式被轉換為bool型別:
3、用一表示式初始化某個變數,或將一表示式賦值給某個變數,則該表示式被轉換為該變數的型別
8.2 算術轉換
8.2.1 有符號與無符號型別之間的轉換
若表示式中使用了無符號數值,所定義的轉換規則需保護運算元的精度。unsigned 運算元的轉換依賴於機器中整型的相對大小,因此,這類轉換本質上依賴於機器。
8.3 其他隱式轉換
8.3.1 指標轉換
在使用陣列時,大多數情況下陣列都會自動轉換為指向第乙個元素的指標:
int ia[10];
int *ip = ia;
c++還提供了另外兩種指標轉換:指向任意資料型別的指標都可轉換為void*型別;整型值常量0可轉換為任意指標型別。
8.3.2 轉換為bool型別
8.3.3 算術型別與bool型別的轉換
8.3.4 轉換與列舉型別
c++自動將列舉型別的物件或列舉成員轉換為整型,其轉換結果可用於任何要求使用整數值的地方。
九、顯示轉換
顯示轉換稱為強制型別轉換(cast),包括以下列名字命名的強制型別轉換操作符:
static_cast、dynamic_cast、const_cast和reinterpret_cast。
9.1 何時需要強制型別轉換
因為要覆蓋通常的標準轉換,所以需顯示使用強制型別轉換。
顯示使用強制型別轉換的另乙個原因是:可能存在多種轉換時,需要選擇一種特定的型別轉換。
9.2 命名的強制型別轉換
C primer(第四版)讀書筆記2
以下幾種情況都可能引發執行時或編譯時錯誤 1 delete不是new分配的空間 2 重複delete new分配的空間兩次以上 3 在釋放動態陣列時忘了方括號對 inti int pi i delete pi vs 2008 會執行時錯誤 string str dwarves delete str ...
C primer(第四版)讀書筆記5
extern int i declares but does not define i int i declares and defines i extern宣告不是定義,也不分配儲存空間。事實上,它只是說明變數定義在程式的其他地方。程式中變數可以宣告多次,但只能定義一次。如果宣告有初始化式,那麼它...
C Primer中文版第四版 讀書筆記
2011.8.10 p46 只有當extern 宣告位於函式外部時,才可以含有初始化式。extern double pi 3.1416 pi 是乙個全域性變數,這是乙個定義 p50 在全域性作用域宣告的const 變數是定義該物件的檔案的區域性變數 僅作用在該檔案中 要使 const 變數能夠在其他...