左值表示式 右值表示式(C/C++)
何謂物件?
這裡所說的物件是廣義上的,而不僅僅是狹義的類/物件(class/object)。
在C/C++中,所謂的物件指的是執行環境中一塊儲存區域(a region of storage),該儲存區域中的內容則代表了該物件的值(value)。注意到我們這裡所說的"代表",對於一個物件,如果我們需要取出它的值,那麼我們需要通過一定的
型別(type)來引用它。使用不同的型別,對同一物件中的內容的解釋會導致
可能得到不同的值,或者產生某些未定義的行為。
何謂變數?
經常有人會把變數與物件二者混淆。所謂變數是一種宣告,通過宣告,
把一個名字與一個物件對應起來,當我們使用該名字時,就表示了我們對該
物件進行某種操作。但是並不是每個物件都有名字,也並不意味著有對應的
變數。比如臨時物件(temporary object)就沒有一個名字與之關聯(不要誤稱
為臨時變數,這是不正確的說法)。
左值 右值
先看一個例子(出自《C專家程式設計》)
一個賦值表示式: X = Y;
在這個表示式裡,符號X的含義是X所代表的地址,這被稱為左值,左值
在編譯時可知,左值表示儲存結果的地方;
在這個表示式裡,符號Y的含義是Y所代表的地址的內容,這被稱為右值,
右值在執行時才可知,如無特別說明,右值表示“Y的內容”。
按照C的定義,左值是一個引用到物件的表示式,通過左值我們可以取出
該物件的值。通過可修改的左值表示式(modifiable lvalue)我們還可以修改
該物件的值。(需要說明的是,在C++中,左值還可以引用到函式,即表達
式f如果引用的是函式型別,那麼在C中它既不是左值也不是右值;而在
C++中則是左值)。因為左值引用到某一物件,因此我們使用&對左值表
達式(也只能對左值表示式和函式)取址運算時,可以獲得該物件的地址
(有兩種左值表示式不能取址,一是具有位域( bit-field )型別,因為實現中
最小定址單位是 byte;另一個是具有register指定符,使用register修飾的變
量編譯器可能會優化到暫存器中).
與左值相對應的另一個概念是右值(rvalue)。在C中,右值也用表示式的
值(value
of the expression)來表達。即
該表示式運算後的結果。這個結果往往並不引用到某一物件,可以看成
計算的中間結果;當然它也可能引用到某一物件,但是通過該右值表達
式我們不能直接修改該物件。
關於++i 和 i++
++i的實現:++i是直接給i變數加1,然後返回i本身,因為i是變數,
所以可以被賦值,
即 int & ++(& i)
{
i=i+1;
return i;
}
當然,以上程式碼只是說明問題,不能執行,只是說明++i是左值表示式
i++的實現:
int ++(int i)
{
int temp=i;
i=i+1;
return temp;}
返回臨時物件,然後臨時物件不存在了,所以,不能再被賦值,因此
是右值表示式