《C++Primer》讀書筆記(四)表達式

基礎

基本概念

  • C++定義了:一元運算符和二元運算符
  • 除此之外,還定義了作用於三個運算對象的三元運算符
  • 函數調用也是一種特殊的運算符

(1)組合運算符和運算對象
- 首先要理解==優先級、結合律以及運算對象的求值順序==

(2)運算對象轉換

(3)重載運算符

(4)左值和右值
- 當一個對象被用作右值時,用的是對象的值
- 當一個對象被用作左值時,用的是對象的身份(內存中的未知)

優先級與結合律

  1. 括號無視優先級與結合律
  2. 優先級與結合律有

求值順序

(1)有4種運算符明確規定了求值順序
- (&&)、(||)、(?:)、(,)

算術運算符

  • 一元運算符的級別最高,然後是乘除法,最低是加減法

    計算結果溢出將導致不可預知的後果

  • 取模(%)運算只支持整數類型

  • 在除法運算中,兩個運算對象的符號相同則商爲正數,否則爲負;C++11新標準規定,商一律向0取整(不管正負,直接切除小數部分)

邏輯和關係運算符

  • 關係運算符作用於算術類型或指針類型
  • 邏輯運算符作用於任何能轉換成布爾的類型

(1)與和或運算符
- 注意“與”運算符的左側想檢測原則,右側不一定會檢測
(2)非運算符
(3)關係運算符
- 滿足左結合律,所以,只要關係運算符兩側的數據類型會馬上轉變爲布爾值,不能再進行連續比較了
(4)相等性測試和布爾字面值

賦值運算符

  • 賦值運算符的左右兩個運算對象類型不同,則==右側運算對象將轉換成左側運算對象==
  • C++11允許用花括號來初始化列表
  • 轉換成左側運算對象時,所佔的空間不能大於目標類型空間

(1)賦值運算滿足右結合律
- 靠右的賦值運算符會先完成結合

(2)賦值運算符的優先級較低
- 在條件語句中,通常爲賦值運算符部分加上括號

(3)切勿混淆相等運算符和賦值運算符

(4)複合賦值運算符
- += -= %= 等等,只執行一次求值,省去了求值拷貝的賦值

遞增和遞減運算符

除非必須,否則不用遞增運算符的後置版本

(1)在一條語句中混用解引用和遞增運算符

auto pbeg=v.begin();
while (pbeg!=v.end()&&*pbeg>=0)
    cout<<*pbeg++<<endl;
  • 此時,由於後置遞增運算符的優先級高於解引用運算符,所以pebg++ 等價於 (pebg++)
  • 由於將會返回未增加的副本,所以能夠實現,顯示第一個值,然後向後移動

(2)運算對象可按任意順序求值
= 不要將遞增運算同時符放在賦值運算符的右邊和左邊

成員運算訪問符

  • 點運算符和箭頭運算符都可以用來訪問成員
  • 其中,點運算符獲取類對象的一個成員
  • 箭頭運算符,表達式 ptr->mem 等價於 (*ptr).mem
string  s1="a string",*p=&s1;
auto n=s1.size(); //運行string對象s1的size成員
n=(*p).size(); //運行p所指對象的size成員
n=p->size(); //等價於(*p).size()

條件運算符

  • 條件運算符(?:)的使用形式:
cond?expr1:expr2

(1) 嵌套的條件運算符

(2) 在輸出表達式中使用條件運算符
- 最好在cond表達式處加上括號,因爲條件運算符的優先級很低

位運算符

  • 位運算符提供檢查和設置二進制位的功能

(1)移位運算符( >> 或 << )

unsigned char bits=0233;
bits<<8;

(2)位求反運算符(~)

unsigned char bits=0227;
~bits;

(3)位與、位或、位異或

(4)使用位運算符

  • ==第138頁==實例

(5)移位運算符
- (<<)移位運算符比的優先級:低於算術運算符、高於關係運算符、賦值運算符、條件運算符

sizeof運算符

  • 對char或者類型爲ichar的表達式執行sizeof運算,結果得1
  • 對引用類型執行sizoof運算得被引用對象所佔空間的大小
  • 對指針執行sizeof運算得到指針本身的所佔空間的大小
  • 對解引用指針執行sizeof運算得到指針指向的對象所佔空間的大小,指針不需有效

逗號運算符

  • 對於逗號運算符來說,首先對左側的表達式求值,然後將求值結果丟棄掉。逗號運算符真正的結果是右側表達式的值。如果右側運算對象是左值,那麼最終的求值結果也是左值

類型轉換

算術轉換

  1. 整型提升
  2. 無符號類型的運算對象
  3. 理解算數轉換

其他隱式類型轉換

  1. 數組轉換成指針
  2. 指針的轉換
    • 整數值0或者字面值nullptr能轉換成任意指針類型
    • 指向任意非常量的指針能轉換成void
    • 指向任意對象的指針能轉換成const void*
  3. 轉換成布爾類型
  4. 轉換成常量
int i;
const int &j=i; //非常量轉換成const int的引用
const int *p=&i; //非常量的地址轉換成const的地址
int &r=j,*q=p; //錯誤,不允許const轉換成非常量
  1. 類類型定義的轉換

顯式轉換

  1. 命名的強制類型轉換,形式:
cast-name<type>(expression)
  • 其中,cast-name是:static_cast、dynamic_cast、const_cast、reinterpret_cast

(1)static_cast

double slope=static_cast<double>(j) / i;
void* p=&d;
double *dp=static_cast<double*>(p);

(2)const_cast
- 只能改變運算對象的底層const

const char *pc;
char *p=const_cast<char*>(pc);

(3)reinterpret_cast
- 爲運算對象的位模式提供較低層次上的重新解釋

int *ip;
char 8pc=reinterpret_cast<char*>(ip);
  1. 舊的強制類型轉換
    • type(expr); //函數形式的強制類型轉換
    • (type)expr; //C語言風格的強制類型轉換
發佈了34 篇原創文章 · 獲贊 5 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章