天天看點

C++ Primer學習筆記之第四章--表達式

4、1 基礎

4.1.1 基本概念

1、左值和右值

(1)C++的表達式要不然是右值(rvalue),要不然就是左值(lvalue)

(2)一個重要原則:在需要右值的地方可以用左值來替代,但不能把右值當成左值使用(有一種情況例外,可以把右值當成左值使用)。

(3)當一個對象被用作右值的時候,用的對象的值(内容),當對象被用作左值的時候,用的是對象的身份(在記憶體中的位置)

(4)需要用到左值的運算符

①指派運算符(需要一個非常量左值)

②取位址符

③内置解引用運算符、下标運算符。

④内置類型和疊代器的遞增減運算符

4.1.2 優先級與結合律

1、複合表達式(compound expression):是指含有兩個或多個運算符的表達式。

(1)括号可以無視優先級和結合律。

4.1.3 求值順序

1、有四種運算符明确規定了運算符對象的求值順序

(1)&&

(2)||

(3)?:

(4),

4.3節練習

4.10:為while循環寫一個條件,使其從标準輸入中讀取整數,遇到42時候停止。

int a;
    while (cin >> a&&a != )
        cout << a << endl;
           

4.11:書寫一條表達式用于測試4個值a、b、c、d的關系,確定a大于b、b大于c、c大于d

int a = , b = , c = , d = ;
    if (a > b&&b > c&&c > d)
        cout << "a>b,b>c,c>d" << endl;
           

4.4 指派運算符

1、指派運算符滿足右結合律

2、指派運算表達式優先級比較低,是以在條件語句中,指派部分通常應該加上括号。

4.5 遞增和遞減運算符

1、

(1)前置版本(++i):先将運算對象加(減1),然後将改變後的對象作為求值結果。

(2)後置版本(i++):先将對象作為求值結果,再給運算對象加1(或減1)

2、運算對象可按任意順序求值

4.7條件運算符

1、格式:

(1)condition為真,執行expr1

(2)condition為假,執行expr2

2、條件運算符可嵌套

3、條件運算符的優先級非常低,是以當一條長表達式中嵌套了(?:),通常需在兩端加上括号。

4、7節練習

4.21:編寫一段程式,使用條件運算符從vector中找到哪些元素的值是奇數,然後将這些奇數值

int a;
    std::vector<int> iv;
    while(cin>>a)
        iv.push_back(a);
    for(auto:vi)
        cout<<((i%==)?:i*);
           

4.22:用條件運算符版本将學生成績分為fail、low pass、pass、high pass四個階層。

int grade;
    cout<<"Enter grade:\n";
    cin>>grade;
    cout<<(grade<?"fail":(grade<?"low pass":(grade<?"pass":"high pass")))<<endl;
           

用if語句寫的版本

int grade;
    cout<<"Enter grade: ";
    cin>>grade;
    if(grade<)
        cout<<"fail"<<endl;
    else if(grade<&&grade>)
        cout<<"low pass"<<endl;
    else if(grade>&&grade<)
        cout<<"pass"<<endl;
    else
        cout<<"high pass"<<endl;
           

4.8 位運算符

1、位運算符作用于整數類型的運算對象,并把運算對象看成是二進制的集合。

(1)位運算符提供檢查和設定二進制位的功能

2、bitset類型,其标準庫類型也可以表示任意大小的二進制位集合。

3、位運算符(滿足左結合律)

(1)~(位求反)

<1>格式:

~expr

(2)<<(左移) >>(右移)

<1>格式:

expr1<<expr2

expr1>>expr2

(3)&(位與)

<1>格式:

expr1&expr2

(4)^(位異或)

<1>格式:

expr^expr

(5)|(位與)

<1>格式:

expr|expr

4、位運算符(又叫IO運算符)滿足左結合律

4.9 sizeof運算符

1、作用:傳回一條表達式或一個類型名所占的位元組數

2、格式:

(1)

sizeof (type);
size expr;
           

3、sizeof運算符可擷取類成員大小而無須提供一個具體的對象。

4.11 類型轉換 ##

1、隐式轉換(implicit conversion):由編譯器自動執行的類型轉換(自動執行,無須程式員介入。)

2、發生隐式轉換的情況

(1)比int類型小的整型值受限提升為較大的整數類型

(2)在條件中,非布爾值轉換成布爾類型

(3)初始化過程中,初始值(literal)轉換成變量類型

(4)指派語句中,右側運算符轉換成左側運算符

(5)算術運算符或關系運算符有多種類型的時候

(6)函數調用的時候

4.11.3 顯式轉換

1、命名的強制類型轉換(cast)

(1)格式: cast-name(expression)

<1>type:轉換的目标類型

<2>expression:要轉換的值

<3>type若是引用類型,則結果是左值

<4>cast-name是以下4種類型

①static_const

②dynamic_cast

③const_cast

④reinterpret_cast

中的一種

(2)static_cast:任何具有明确定義的類型轉換,隻要不包含底層const,都可以使用。

<1>例:

double slope=static_cast<double>(j)/i;
           

<2>優點:較大算術類型轉換為較小算術類型。

(3)const_cast:隻能改變運算對象的底層const

<1>例:

const char c='k';
char *pc=&c;
char *p=const_cast<char *>(pc);
//正确,但是通過p寫值是未定義的行為 
           

<2>優點:const_cast能去掉底層const,将一個指向常量的指針轉換為一個指向不一定是常量的指針。

(4)reinterpret_cast:通常為運算對象的位模式提供較低層次上的重新解釋(一般用于不同類型的指針轉換)

<1>例:

int *ip;
char *pc=reinterpret_cast<char *>ip;
//pc所指向的對象為int而非字元
string str(pc);     //運作時發生錯誤   
           

2、舊式的強制類型轉換

(1)格式:

type(expr);     //函數形式的強制類型轉換
(type)expr;     //C風格的強制類型轉換
           

4.11.3節練習

4.36:假設i是int類型,d是double類型,書寫表達式i*=d使其執行整數類型的乘法而非浮點類型的乘法

int i=;
    double d=;
    i*=static_cast<double>(d);
    i*=d;
    cout<<i<<endl;
           

4.37:用命名的強制類型轉換改寫下列舊式的轉換語句

int i;
double d;
const string *ps;
char *pc;void *pv;

(a)pv=(void *)ps;
    pv=static_cast<void *>(const_cast<string *>(ps));

(b)i=int(*pc);
    i=static_cast<int>(*pc);

(c)pv=&d;
    pv=static_cast<void *>(&d);

(d)pc=(char *)pv;
    pc=static_cast<char *>(pv);
           

繼續閱讀