1. 程式人生 > >C++左值表示式

C++左值表示式

    今天我們將要談論的話題——左值表示式——相信不少人從各種途徑中或許瞭解到一些,若是對這個概念還是模模糊糊,那接著看下去就對了,若是對這個概念十分清楚了,那就幫我找找問題,不吝賜教一下吧!

    或許你是從書中瞭解到這個概念,有些老書可能會寫左值表示式就是可以放在賦值運算子左側作為左運算元的表示式,這種說法在早期或許是沒什麼問題的,畢竟早期的左值定義是基於賦值運算子需求的,它認為能作為賦值運算子左運算元的表示式就是左值。但這個說法也有一些地方將難以自圓其說,比如陣列名,陣列是聚集,不是標量型別(標量型別,實際上指的就是C++基本型別,如int, char之類),我們是無法用一個值來表示一個數組的,而賦值運算子則要求左運算元是一個標量型別(結構例外),這顯然不合理。因此,早期將陣列名定為右值,陣列作為完整物件,理應可以取地址,但取地址運算子又要求運算元為左值,這與定義又矛盾了。

    說了左值過去的說法,那現在就來講講左值現在的說法吧!我們判斷一個表示式是否為左值表示式,關鍵在於:它必須指示一個物件,不管這個物件是有效還是無效,完整還是不完整(關於完整型別,不完整型別下面會提到),另外加一點,在C++中,規定包括非靜態類成員函式之外的函式都是左值表示式。下面舉個例子:

int i;
int *p = &i;

我們且不管p指向的i內容有效無效,i和p都是指示一個物件的,且具有物件型別,所以它們都是左值,但是雖然&i也有物件型別,但是它並沒有指示一個物件,所以它不是左值。這裡或許有些人會感動迷糊,&i不是表示了一個地址了麼,怎麼說是沒有指示一個物件呢?在這裡,我就引用一句李普曼大師在C++ Primer5裡寫到的一句話:變數是左值!注意這裡的變數說的可不是臨時變數!我們應該嚴格區別一下。由此,我們再看上面,&i是一個臨時變數,所以它不算是左值!

    我們在上面提到過完整型別和不完整型別,不完整型別其實就是缺少足夠的資訊,舉個例子,比如缺少定義以致不能明確其大小,前向宣告也算是常見的一種不完整型別:

class MyClass;
struct S;

看到這裡,大家都恍然大悟了吧,原來是這種玩意兒!