zoukankan      html  css  js  c++  java
  • 理解lvalue和rvalue

    今天看C++模板的资料,里面说到lvalue,rvalue的问题,这个问题以前也看到过,也查过相关资料,但是没有考虑得很深,只知道rvalue不能取地址,不能赋值等等一些规则。今天则突然有了更深层次的理解(也可以说是顿悟,耗时不过几秒钟),记录下来。

    下面是我对这两个单词字面的意思的猜测:

    • lvalue估计来源于left value。 在赋值语句中lvalue = rvalue;位置处于左边。就是可以修改的值。
    • rvalue估计来源于right value。处于赋值语句右边,是只读的不可修改的值。

    接下来是我所悟到内容的详细分析

    • lvalue是可以赋值的,说明它是一个变量,它在内存中一定存在,一定有地址。所以&lvalue是有效的,能取到在内存中的地址。

      访问lvalue一定会导致CPU访问存储器(相对较慢的操作)。

      lvalue的例子:

      [cpp] view plaincopy
       
      1. int a;  
      2. a = 10; // a是lvalue。  
      3. int* p = &a; // &a是rvalue。  
      4. &a = 0; //错误,&a不是lvalue,因为a的地址一旦分配好了,就不能改变了。  
    • rvalue是不可以赋值的,它不是一个变量,在内存中没有存在,没有地址。它要么是存在于CPU的寄存器中,要么是存在于指令中(立即数)。所以只要对rvalue取地址,那么就一定是错误的(编译器会抱怨的)。

      访问rvalue不会导致CPU访问存储器(对立即数和寄存器的访问很快)。

      rvalue的例子:

      [cpp] view plaincopy
       
      1. int a;  
      2. a = 10; // 10是rvalue,它没有地址,&10就是错误的表达式。从汇编语言的角度来看,10是直接存在于MOV指令中的立即数。  
      3. 10 = a; // 错误,10是rvalue,不可赋值。  
      4. //函数返回值属于rvalue,因为返回值通常用CPU寄存器传递,没有地址。  
      5. int foo()  
      6. {  
      7.     return 0;  
      8. }  
      9. int b = foo(); //没问题,函数返回值是rvalue。  
      10. int* p = &foo(); //错误,rvalue没有地址。  
      11. void bar(int& i)  
      12. {  
      13. }  
      14. bar(foo()); //错误,bar函数参数需要的是lvalue。  
    • 函数的返回值是rvalue,对于返回int, char 等这样最基本的类型,是通过CPU寄存器返回的,因此返回值没有地址是可以理解的。但是如果函数返回的是一个用户自定义类型的对象,肯定不可能通过寄存器来返回这个对象值的(寄存器大小数量都有限,对象的大小可以非常大),那究竟是怎样返回对象的呢?
      [cpp] view plaincopy
       
      1. class UDT  
      2. {  
      3.   int data[100];  
      4. public:  
      5.   UDT()  
      6.   {  
      7.     printf("construct/n");  
      8.   }  
      9.   BBB& operator = (BBB& )  
      10.   {  
      11.     printf("operator =/n");  
      12.     return *this;  
      13.   }  
      14. };  
      15. UDT foo()  
      16. {  
      17.   return UDT();  
      18. }  
      19. void main()  
      20. {  
      21.   UDT obj = foo();  
      22. }  
      23. //输出:  
      24. construct  

      带着疑问,我查了查vc编译出来的代码,原来obj这个局部变量的地址被压入了堆栈,foo函数内部以堆栈上的obj地址作为this指针调用了UDT的构造函数。噢,难怪执行UDT obj = foo();这个语句只有调用了一次构造函数,而没有调用operator =,这都是因为函数返回值必须是rvalue这个规则所带来的好处,如果返回值是一个lvalue,那么这个语句一定会调用operator = 运算符。

    文章来自:http://blog.csdn.net/rogerhe/article/details/6410993

  • 相关阅读:
    例7-13
    例7-11
    例7-1
    例6-5
    例6-3
    例6-2
    例6-1
    例5-9
    例5-8
    例5-7
  • 原文地址:https://www.cnblogs.com/ewyb/p/4079437.html
Copyright © 2011-2022 走看看