• 理解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

  • 相关阅读:
    leetcode 29-> Divide Two Integers without using multiplication, division and mod operator
    ros topic 发布一次可能会接收不到数据
    python中的print()、str()和repr()的区别
    python 部分函数
    uiautomatorviewer错误 unable toconnect to adb
    pyqt 不规则形状窗口显示
    appium 计算器demo
    Spring 3.0 注解注入详解
    Spring Autowire自动装配
    restful 学习地址
  • 原文地址:https://www.cnblogs.com/ewyb/p/4079437.html
Copyright © 2020-2023  润新知