讓我們先看看一些常見的左值和右值舉例:
|
對於每一個表達式,其要麼是一個左值(lvalues),要麼是一個右值(rvalue)。
右值的類型總是完整類型或者void類型。注意兩點:(1)void類型(非完整類型)是右值;(2)當右值的類型不是void類型時,其必須是完整類型,因爲需要計算它的值。由此可知,非void的非完整類型是左值。
C++中的左值和右值
注1:對象類型爲非函數、非引用、非void的類型;左值所對應的對象不一定實際存在。例如:char* p; *p這個左值所對應的對象目前是不存在的。 部分右值表達式也可以對應對象。例如,那些調用構造函數和調用那些返回類對象的函數的表達式,這些表達式可以調用相應對象的成員函數,但這些表達式是右值(此時,該右值可能是可修改的右值)。 |
注3:當左值類型T爲非函數、非數組類型時,左值可以被轉換爲右值。如果T是非void的非完整類型,那麼此時左值不應該被轉化爲右值來使用;如果該左值所對應的對象不是類型T的對象,也不是由T派生的類型的對象,或者該對象沒有被初始化,那麼發生這種轉換的程序將產生未定義行爲。 如果T是非類類型,那麼轉換得到的右值的類型是T的CV-qualified版本;否則,右值類型是T。 左值所對應的對象所包含的值就是右值的結果。 在發生這種轉換時,左值的值並不是一定被計算。例如:當運算符sizeof的操作數發生這種轉換時,並不需要訪問左值的值,因爲該運算符不需要計算它的操作數。 |
左值分爲可修改的左值(modifiable)和不可修改的左值(nonmodifiable)。
如果要修改一個對象,該對象必須是左值;例外情況是,類類型的右值也可以在某些情形下修改它所對應的對象。例如,函數調用返回的類是右值,但可以調用其成員函數修改該對象。
由const限定的表達式不可以被修改;除非這是一個類類型,並且擁有mutable成員,那麼該mutable成員可以被修改。
非類類型的右值總是由CV-qualifiers限定,類類型的右值可以沒有CV-qualifiers。
部分內置運算符需要左值操作數。例如,所有內置賦值運算符要求它們的左操作數是一個左值(此時還是一個可修改的左值)。
部分內置運算符需要右值操作數,並且產生右值。例如,一元運算符和二元運算符“+”要求操作數爲右值,並且它們產生的結果也爲右值。
部分內置運算符和函數調用產生左值。例如,如果E是一個指針類型的表達式,那麼*E是一個左值表達式(注:*運算符的操作數是左值,產生一個左值)。又如,函數 int& f();產生一個左值,因此f()的調用是一個左值表達式。
如果一個程序試圖通過一個左值的非下列類型去訪問存儲在對象中的值,那麼該行爲是未定義的。
注2:自定義運算符是函數,這類運算符是否需要或者產生左值取決於它們的參數和返回值類型。 |