C++ 中的左值、右值、左值引用、右值引用、引用分別是什麼,有哪些關係?

1.左值與右值

百度百科上說

L-value中的L指的是Location,表示可定址。A
value (computer science)that has an address.

R-value中的R指的是Read,表示可讀。in
computer science, a value that does not have an address in a computer language

但是我在某些地方又看到別人說L-value,R-value,

L:left R:right,當然我剛開始也以為是這個意思,畢竟翻譯為左值右值,讓人難免產生遐想。

那請問到底L,R代表的是什麼意思呢?

此外:在該篇博客上看到(i++)++,這是錯誤的,博主說i++返回一個臨時變數,臨時變數具有const屬性(這個我在c++ primer上沒看到,請問這句話對嗎,我看csdn上有人說沒這概念,有人說這是對的),不可以更改,所以是錯誤的。以下是我的理解,麻煩看一下對不對?

我:

const int temp1 = i + 1;//括弧裡面的i++
const int temp2 = i + 1;//括弧外面的i++,因為i是先計算後自增,所以進行括弧外面的i並不是自增運算後的i,而是自增運算之前的i?
temp1 = temp2;//出錯,temp1 是const 變數,所以不允許賦值,出現錯誤

另我在dev C++中調試的時候說, [Error] lvalue required as
increment operand,需要一個左值作為一個增量的立即數?應該是我左值概念沒有理解清楚(我的理解就是左值是地址,右值是具體數值),所以這個我也不太理解。

2.C++primer(第五版)中說「當我們使用術語『引用』時,其實指的是『左值引用」

這裡的左值引用到底怎麼理解呢

int i = 0;
int a = i;
int b = i;

(1)可以這樣用語言描述嗎 ?如「a引用了一個int型的數i,或者i的引用是a」?我不知道這用官方的術語該怎麼講出來

(2)看了百度百科的「左值與右值」,根據上面說的,b = i,是將i的右值賦給了b的左值,那麼 int a = i ; 該怎麼說呢?能說將i的右值賦給了a的左值嗎?

(3)對於int i = 1;我們說的變數類型是指i的左值類型是int,還是右值類型是int,還是就是我說錯了?因為看到書上說「引用的類型就是左值的類型」,左值不是就是一個變數的地址嗎?也能有類型?(page64(中文版) exercise2.37 題目)

以上如有說錯,懇請友情指出,不勝感激!另外有時候大神看到了另外一個大神已經解答這個題目,就不想在重複回答了,我希望大神們看到之後,如果有什麼補充的,額外的也可以說一下,先行謝過!


左值右值是非常非常久遠的概念,一開始l和r就是代表left和right。但是隨著語言的發展單純左右已經無法區分lvalue和rvalue的區別了。C++11中已經不是這麼籠統的概念了。一般而言,可以取地址、有名字的就是左值,反之就是右值。更為細緻而言,根據C++11標準,每個表達式可分為lvalue、xvalue(expiring value)或prvalue(pure rvalue)。

有兩個概念:變數表達式都是左值。左值可以當右值使用,並且在這種情況下用的是其內容。

所以對於「b = i」而言,是將i的左值作為右值使用,取i的變數的值,賦值給b的左值。

此外,臨時對象不是const。++/--,前綴版本返回左值,後綴版本返回右值。

左值引用()這個概念和右值引用()是對應的。左值引用就是常規引用,右值引用是C++11的新概念。右值引用只能綁定到一個右值。

2.37翻譯錯了。原文為:「Assignment is an example of an expression that yields a
reference type. The type is a reference to the type of the left-hand operand.」 因為賦值操作符也是一個函數,因此也會有返回值,返回值的類型,是其左側運算對象的引用類型。比如『i = 3』,返回值類型就是『int』。

最後,給你個官方定義:

  • —An lvalue (so called, historically, because lvalues could appear on the left-hand side of an assignment
    expression) designates a function or an object.

    [Example: If E is an expression of pointer type, then
    *E is an lvalue expression referring to the object or function to which E points. As another example,
    the result of calling a function whose return type is an lvalue reference is an lvalue. — end example ]

  • — An xvalue (an 「eXpiring」 value) also refers to an object, usually near the end of its lifetime (so that its
    resources may be moved, for example). An xvalue is the result of certain kinds of expressions involving
    rvalue references (8.3.2).

    [Example: The result of calling a function whose return type is an rvalue
    reference is an xvalue. — end example ]

  • — A glvalue (「generalized」 lvalue) is an lvalue or an xvalue.

  • — An rvalue (so called, historically, because rvalues could appear on the right-hand side of an assignment
    expressions) is an xvalue, a temporary object (12.2) or subobject thereof, or a value that is not
    associated with an object.

  • — A prvalue (「pure」 rvalue) is an rvalue that is not an xvalue.

    [ Example: The result of calling a function
    whose return type is not a reference is a prvalue. The value of a literal such as 12, 7.3e5, or true is
    also a prvalue. — end example ]

推薦資源:

C++ Rvalue References Explained

C++ - What are rvalues, lvalues, xvalues, glvalues, and prvalues?

FCD N3092

深入理解C++11 (豆瓣)


L-value的L代表蘿莉(luo li),可結識可誘拐,全世界的怪蜀黍都可以喂她吃棒棒糖;

R-value的R代表人妻(ren qi),可結識不可誘拐,一旦NTR了那就是你的人了。

至於Left和Right嘛,都是後人牽強附會。(逃


不要糾結概念,多寫代碼,自然就明白了

上上上個月我讀到這塊的時候發現C++的左右值和C的左右值相比太複雜了,索性那段就略過了

上上個月我在看知乎上關於C++11右值引用的回答的時候瞬間理解了C++的左右值的概念

當然這和前面一個月寫的代碼的積累也有關係

再補充幾句

如果你很清楚C語言範疇的左右值的概念,那麼你在使用C++的左右值的時候不會出錯

然後多寫代碼,你就能理解C++相比C多出的那部分左右值的概念


1. 左值可以放到等號左邊,右值只能放到右邊。如有需要,左值可以轉換為右值,反之則不可。

2. 左右值是表達式的屬性。單個變數名是id表達式,但表達式不都是單個變數。


C++11的值分類有三種,lvalue xvalue prvalue。另外lvalue和xvalue合稱glvalue,xvalue和prvalue合稱rvalue。

ISO C++11 3.10

— An lvalue (so called, historically, because lvalues could appear on the left-hand side of an assignment expression) designates a function or an object. [ Example: If E is an expression of pointer type, then *E is an lvalue expression referring to the object or function to which E points. As another example, the result of calling a function whose return type is an lvalue reference is an lvalue. — end example ]

— An xvalue (an 「eXpiring」 value) also refers to an object, usually near the end of its lifetime (so that its resources may be moved, for example). An xvalue is the result of certain kinds of expressions involving rvalue references (8.3.2). [ Example: The result of calling a function whose return type is an rvalue reference is an xvalue. — end example ]

— A glvalue (「generalized」 lvalue) is an lvalue or an xvalue.

— An rvalue (so called, historically, because rvalues could appear on the right-hand side of an assignment expression) is an xvalue, a temporary object (12.2) or subobject thereof, or a value that is not associated with an object.

— A prvalue (「pure」 rvalue) is an rvalue that is not an xvalue. [ Example: The result of calling a function whose return type is not a reference is a prvalue. The value of a literal such as 12, 7.3e5, or true is also a prvalue. — end example ]

1. rvalue解釋成readable value很勉強,lvalue解釋成location value倒是很恰當。當然它本來就是right value和left value,但是這是C,C++中左右值變得複雜而開始詞不達意。

2 博主說i++返回一個臨時變數,臨時變數具有const屬性

------------------

非類類型的prvalue永遠沒有const修飾(3.10 4)。不能自增是因為它不是可修改的左值。

3. 以下是我的理解,麻煩看一下對不對?

const int temp1 = i + 1;//括弧裡面的i++

const int temp2 = i + 1;//括弧外面的i++

因為i是先計算後自增,所以進行括弧外面的i並不是自增運算後的i,而是自增運算之前的i?

temp1 = temp2;// 出錯,temp1 是const 變數,所以不允許賦值,出現錯誤 另我在dev C++中調試的時候說, [Error] lvalue required as increment operand,需要一個左值作為一個增量的立即數?應該是我左值概念沒有理解清楚(我的理解就是左值是地址,右值是具體數值),所以這個我也不太理解。

------------------

見上,i++是一個prvalue,沒有const。

int i = 0; int a = i; int b = i;

4. 可以這樣用語言描述嗎 ?如「a引用了一個int型的數i,或者i的引用是a」?

------------------

我是這麼叫的:a是一個i的引用。反過來個人認為不對。

5. 看了百度百科的「左值與右值」,根據上面說的,b = i,是將i的右值賦給了b的左值,那麼 int a = i ; 該怎麼說呢?能說將i的右值賦給了a的左值嗎?

------------------

不是「i的左值」,是「i是左值」。i是左值,所以用它初始化b的時候經過左值-右值轉換得到一個右值,用它來初始化b。a是一個(左值)引用,它需要一個左值初始化,這裡沒有左值-右值轉換。

6. 對於int i = 1;我們說的變數類型是指i的左值類型是int,還是右值類型是int,還是就是我說錯了?因為看到書上說「引用的類型就是左值的類型」, 左值不是就是一個變數的地址嗎?也能有類型?

.-----------------

同上,左值和右值指的是值的分類,並不是「存儲位置和其中的值」這種東西。一個值是有類型的。i的類型就是int,它是左值,沒有什麼左值類型右值類型。「引用的類型就是左值的類型」不知道指的什麼。

另外補充一點,現在的C++(還有C)的值分類早就不能靠能否出現在=左邊來區分了。甚至C和C++也是完全不同的。


左值表達式表示的是對象,右值表達式表示的是對象的值。

右值比如 部分表達式產生的值,後增運算符i++,函數返回值

右值引用,只能綁定到將要銷毀的對象,且對象沒有其他用戶。所以我們可以將即將銷毀的對象通過右值引用「移動」到新的變數中,幫它找到個「歸屬」。右值引用也僅僅是個變數。

你說的int i = 1; i是一個對象是一個變數是左值,1則是對象的值是右值

看下這篇博客

http://m.blog.csdn.net/blog/wwh578867817/42084887

如果有問題一起討論哈


問題本身大家解釋的比較清楚了,但個人認為授人以魚不如授人以漁。給題主句忠告:這種基礎問題,那麼多技術網站上早就討論爛了,你偏偏跑去看百度百科,甚至魚龍混雜良莠不齊的中文技術博客,有點緣木求魚的感覺,早晚會吃虧。

關於c++本身,cplusplus.com是我最常查詢的網站。有人更喜歡cppreference.com.後者甚至存在一個中文版本cppreference.com,不過不是很全。

碰到什麼靠以上兩個網站依然理解不了的概念或解決不了的編譯錯誤,請去Stack Overflow.

SO上解釋你提的問題的帖子:

c++ - What are rvalues, lvalues, xvalues, glvalues, and prvalues?

不要拿英文水平不足當借口,如果英文水平真的影響到你閱讀SO上的帖子,那麼只能說對你而言提高英語水平是和提高編程水平是同等重要的事。


@李元奇

"此外,臨時對象不是const。"


我個人的理解是右值是臨時值,是即將銷毀的對象,比如int i=1,右邊的1就是用完就銷毀,而右值引用就是接管這些臨時變數的地址空間(二者的地址是一樣的)。其餘的我們可以認為是左值,普通的引用就是接管這樣的地址空間。


我一直以為左值就是能放到賦值符號(=)左邊的值


lvalue是location value,rvalue是register value。

詳情請見Jack Purdum的《C#3.0 面向對象的編程》第67頁。


推薦閱讀:

對於LLVM之類的編譯器是如何實現在構造SSA形式的IR的時候,計算出def-use鏈?
有沒有內容類似於《Python源碼剖析》,但內容更新過,針對新版本的Python書籍?
任何編程語言都可以編譯為原生的機器碼嗎?

TAG:編程語言 | C | 編譯原理 | CPrimer |