天天看點

C++ 中左值和右值的探讨

我的主力部落格:

對于 c++ 中的左值和右值,我們通常的說法是:當一個對象被用作右值的時候,用的是對象的值(内容);當對象被用作左值的時候,用的是對象的身份(在記憶體中的位置),這句話來自于  第 121 頁,那麼,對于這句話,該作何了解呢?下面我想來談談我的看法:

iso c++03規定表達式必須是左值或右值之一,而在iso c++11中,左值性被正式地擴充為更複雜的值類别,對于一個變量來說,與它相關的有兩個部分:一是變量在記憶體中的位址,二是這個變量在記憶體中的位址中所存儲的資料。當我們使用變量在記憶體中的位址的時候,譬如給變量指派,實際上使用的是變量的身份,而不是變量的值(内容),此時,變量是被用作左值的;當我們使用變量的值(内容)的時候,譬如把變量的值賦給另一個對象的時候,變量是被用作右值的。由此可見,變量既可以被用作左值也可以被用作右值,那麼變量究竟是左值還是右值呢? 第 121 頁中又寫到, 一個重要的原則(有一種例外)是在需要右值的地方可以用左值代替,但是不能把右值當作左值 ,由此可見,一個變量表達式是左值。

以上說了那麼多其實還沒有說到判斷一個表達式究竟是左值還是右值的方法,那麼,該怎樣判斷一個表達式是左值還是右值呢?對于“當對象被用作左值的時候,用的是對象的身份(在記憶體中的位置)”這句話,我們是不是可以這樣了解,當一個表達式 在自身所在的表達式結束之後有持久的身份(在記憶體中的位置) 可以使用的時候,它就是一個左值,即 可以對這個表達式運作結束之後取得持久的位址的時候,說明這個表達式是一個左值,否則是一個右值,為什麼我們要強調 在自身所在的表達式結束之後有持久的身份(在記憶體中的位置) 這句話呢?因為我們使用一個表達式作為左值的時候早已經超出了這個表達式範圍本身來使用它,如果離開這個表達式自身的範圍就得不到這個表達式的位址的話,用表達式作為左值就沒有任何意義了,下面通過一個例子來細細剖析這段内容:

對于前置遞增(遞減)運算符和後置遞增(遞減)運算符的表達式,究竟哪一個是左值哪一個是右值呢?針對前置遞增和後置遞增的情況,我們來分析一下,前置遞減和後置遞減可以同理分析:

<code>++i</code> 這個前置遞增表達式,是把 i 的值加 1 然後傳回 i 的值,這個表達式的傳回值是 i,對 i 取位址可以得到持久的位址,是以,對于前置遞增表達式,它是一個左值;

<code>i++</code> 這個後置遞增表達式,是把 i 值的副本傳回後再把 i 加 1,這個表達式傳回的實際上是一個 i 的副本(臨時量),而不是 i 本身(i 本身已加

1),是以,在這個表達式運作結束的時候,我們對這個表達式取位址,将得不到一個持久的位址,因為這個臨時量随着表達式的結束已經不複存在了,是以,對于後置遞增表達式,它是一個右值;

對于前置遞增和後置遞增運算符,它們操作對象究竟是一個左值還是右值呢?<code>++i</code> 這個前置遞增表達式,最後傳回的是 i 本身,它使用的是 i 的身份,是以此處的

i 是作為左值使用的,<code>i++</code> 這個後置遞增表達式,最後傳回的是 i 的副本,它使用的是 i 的内容,是以此處的 i 是作為右值使用的。

我們來看看對于表達式 <code>++i--</code> 加上括号,變成 <code>++(i--)</code> 之後,這個表達式是不是合法的呢?通過上面的分析我們知道,前置遞增(遞減)運算符的操作對象是一個左值,後置遞增(遞減)運算符的操作對象是一個右值,但是<code>i--</code> 這個表達式是一個右值,而前置遞增(遞減)運算符的操作對象是一個左值,是以,<code>++(i--)</code> 這個表達式是不合法的。

通過以上的分析我相信對于 c++ 中的左值和右值能有一個深刻地了解了,其實說到底就一句話,這裡最後再強調一下: 可以對這個表達式運作結束之後取得持久的位址的時候,說明這個表達式是一個左值,否則是一個右值

ps: 以上内容系原創,轉載請注明位址

繼續閱讀