如何理解左操作數必須爲左值

本文轉載自 : _Hebrew博客
聲明:本博文用於學習總結及工作心得

在C語言中經常會遇到一個問題就是做操作數必須爲左值,看一下代碼:

int a=1,b=2;

a<b?a:b=10;

在C++編譯器環境下,能正常運行,沒有錯誤,但是在C編譯器下卻會報錯:

error C2106 “=”:做操作數必須爲左值

什麼是左值?

首先需要明白什麼是表達式:

表達式由一個或多個操作數通過操作符組合而成。最簡單的表達式僅包含一個字面值常量或變量。較複雜的表達式則由操作符以及一個或多個操作數構成。

什麼是左值:

不嚴謹的說法是,左值右值的區分在於位於等號的那一側,左側的是左值,通常是一個變量,右側的是右值,可以是一個變量,或者是一個表達式。

C++ 中存在兩種表達式:左值可以出現在賦值語句的左邊或右邊。右值只能出現在賦值的右邊,不能出現在賦值語句的左邊。

a<b?a:b 

是一個表達式,返回的是a的值或者b的值,並不是一個變量,常數不是變量(變量:一段連續內存空間的別名),所以10不能賦值給一個常數(常數是恆定不變的,一切常數、字符和字符串都是右值),沒有存儲結果的空間,也就不能賦值;

將代碼修改一下:

*( a < b ? &a : &b ) = 10;  

這樣表達式返回的是一個(a的地址或者b的地址) 相當於*p;再通過取地址,操作地址所指向的內存空間進行間接賦值

左值在編譯時可知,左值表示存儲結果的地方,所以簡單理解,左值就是必須有存儲結果的地方,有內存空間;至於C++可以運行成功是因爲C++編譯器已經優化過,表達事返回的並不是a的內容(b的內容) ,而是一個變量 ;

特別是操作符重載時,進行鏈式編程時:

//自定義類型AA

class AA
{

private :
    int a,b;

public:
    AA(int a,int b)
    {

        this->a = a;

        this->b = b;

    }

    friend void operator <<(ostream &out, AA &a1);

};

    AA a1( 1, 2);

    cout << a1;
    cout << a1 << endl;

//重載函數爲:

void operator <<(ostream &out, AA &a1 )
{
    cout<< a1.a << a1.b;
    return;
}

這裏的做操作是cout

這時候 運行 cout << a1 ;沒有錯誤

運行下面一句 cout << a1 << endl; 編譯器報錯: 左操作數必須爲左值

首先 cout << a1 返回 void
而後就有 void << endl; void 不能充當做操作數,而且必須要ostream 類型的對象做參數;所以需要返回一個對象的引用(函數返回值當左值時,必須返回一個對象的應用 )

所以需要講函數返回值修改爲 ostream&

ostream& operator <<(ostream &out, AA &a1 )
{
    cout<< "我是cout << 重載函數" << endl;
    cout<< a1.a << "," << a1.b;

    return;
}

記得類中聲明友員函數的地方,也需要修改函數返回值;修改後:

friend ostream& operator <<(ostream &out, AA &a1);

運行後返回
我是cout << 重載函數
1,2
這樣就正確輸出了


補充 : 左值這個名詞,之前一直認爲必須是個可以被賦值的的東西
也就是必須有自己的空間可以賦值,
看了這篇博文之後,也有了更加深入的理解,也是知道了右值這個東西

這裏引用一句:

(常數是恆定不變的,一切常數、字符和字符串都是右值),沒有存儲結果的空間,也就不能賦值;

發佈了65 篇原創文章 · 獲贊 60 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章