轉自http://www.cnblogs.com/areliang/archive/2011/11/16/2251480.html
今天看C++模闆的資料,裡面說到lvalue,rvalue的問題,這個問題以前也看到過,也查過相關資料,但是沒有考慮得很深,隻知道rvalue不能取位址,不能指派等等一些規則。今天則突然有了更深層次的了解(也可以說是頓悟,耗時不過幾秒鐘),記錄下來。
下面是我對這兩個單詞字面的意思的猜測:
- lvalue估計來源于left value。 在指派語句中lvalue = rvalue;位置處于左邊。就是可以修改的值。
- rvalue估計來源于right value。處于指派語句右邊,是隻讀的不可修改的值。
接下來是我所悟到内容的詳細分析
-
lvalue(左值)是可以指派的,說明它是一個變量,它在記憶體中一定存在,一定有位址。是以&lvalue是有效的,能取到在記憶體中的位址。
通路lvalue一定會導緻CPU通路存儲器(相對較慢的操作)。
lvalue的例子:
- int a;
- a = 10; // a是lvalue。
- int* p = &a; // &a是rvalue。
- &a = 0; //錯誤,&a不是lvalue,因為a的位址一旦配置設定好了,就不能改變了。
-
rvalue是不可以指派的,它不是一個變量,在記憶體中沒有存在,沒有位址。它要麼是存在于CPU的寄存器中,要麼是存在于指令中(立即數)。是以隻要對rvalue取位址,那麼就一定是錯誤的(編譯器會抱怨的)。
通路rvalue不會導緻CPU通路存儲器(對立即數和寄存器的通路很快)。
rvalue的例子:
- int a;
- a = 10; // 10是rvalue,它沒有位址,&10就是錯誤的表達式。從彙編語言的角度來看,10是直接存在于MOV指令中的立即數。
- 10 = a; // 錯誤,10是rvalue,不可指派。
- //函數傳回值屬于rvalue,因為傳回值通常用CPU寄存器傳遞,沒有位址。
- int foo()
- {
- return 0;
- }
- int b = foo(); //沒問題,函數傳回值是rvalue。
- int* p = &foo(); //錯誤,rvalue沒有位址。
- void bar(int& i) // 右值是臨時對象,是const類型,不能将非const 類型對象綁定到const對象上
- //反之可以,可以将const對象綁定到非const對象上
- {
- }
- bar(foo()); //錯誤,bar函數參數需要的是lvalue。
- 函數的傳回值是rvalue,對于傳回int, char 等這樣最基本的類型,是通過CPU寄存器傳回的,是以傳回值沒有位址是可以了解的。但是如果函數傳回的是一個使用者自定義類型的對象,肯定不可能通過寄存器來傳回這個對象值的(寄存器大小數量都有限,對象的大小可以非常大),那究竟是怎樣傳回對象的呢?
- class UDT
- {
- int data[100];
- public:
- UDT()
- {
- printf("construct/n");
- }
- BBB& operator = (BBB& )
- {
- printf("operator =/n");
- return *this;
- }
- };
- UDT foo()
- {
- return UDT();
- }
- void main()
- {
- UDT obj = foo();
- }
- //輸出:
- construct