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

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

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

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

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

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

    lvalue的例子:

    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的例子:

    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寄存器返回的,因此返回值没有地址是可以理解的。但是如果函数返回的是一个用户自定义类型的对象,肯定不可能通过寄存器来返回这个对象值的(寄存器大小数量都有限,对象的大小可以非常大),那究竟是怎样返回对象的呢?
    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

理解lvalue和rvalue的更多相关文章

  1. [C++] Lvalue and Rvalue Reference

    Lvalue and Rvalue Reference int a = 10;// a is in stack int& ra = a; // 左值引用 int* && pa ...

  2. 理解C++ lvalue与rvalue

    一个众所周知的危险错误是,函数返回了一个局部变量的指针或引用.一旦函数栈被销毁,这个指针就成为了野指针,导致未定义行为.而左值(lvalue)和右值(rvalue)的概念,本质上,是理解“程序员可以放 ...

  3. C中的lvalue和rvalue

    该贴子第一条回答虽然浅尝辄止,但还是很有参考价值. https://www.quora.com/What-is-lvalue-and-rvalue-in-C IBM一个简单的说法是: "-通 ...

  4. L-value 和 R-value.

    An L-value is something that can appear on the left side of an equal sign, An R-value is something t ...

  5. 左值 lvalue,右值 rvalue 和 移动语义 std::move

    参考文章: [1] 基础篇:lvalue,rvalue和move [2] 深入浅出 C++ 右值引用 [3] Modern CPP Tutorial [4] 右值引用与转移语义 刷 Leetcode ...

  6. C++ lvalue(左值)和rvalue(右值)

    lvalue(左值)和rvalue(右值) 昨天写代码遇见一个这样的错误:{ "cannot bind non-const lvalue reference of type 'int& ...

  7. C++11标准之右值引用(rvalue reference)

    1.右值引用引入的背景 临时对象的产生和拷贝所带来的效率折损,一直是C++所为人诟病的问题.但是C++标准允许编译器对于临时对象的产生具有完全的自由度,从而发展出了Copy Elision.RVO(包 ...

  8. C++11中rvalue references的使用

    Rvalue references are a feature of C++ that was added with the C++11 standard. The syntax of an rval ...

  9. 对象复制问题 && lvalue-rvalue && 引用

    按值传递实参到函数和函数返回临时变量的副本,函数的效率对执行性能来说至关重要 如果避免这样的复制操作,则执行时间可能会大大缩短. class CMessage { private: char * m_ ...

随机推荐

  1. [LOJ6179]Pyh的求和

    首先有一个等式是$\varphi(ab)=\frac{\varphi(a)\varphi(b)d}{\varphi(d)}$,其中$d=(a,b)$,这个比较好证,直接按展开式计算可得$\varphi ...

  2. ArrayList之扩容与迭代器

    1. 扩容 ArrayList扩容包括ensureCapacity(对外开放)和ensureCapacityInternal(内部隐式调用)两个接口: 1' 两者都调用ensureExplicitCa ...

  3. PHP数组和数据结构(上)

    1.数组的声明 两种方法: 直接给数组元素赋值 使用array()函数声明 说明: (1)索引数组的下标可以是非连续的值,只要在初始化时指定非连续的下标值即可 如果指定的下标值已经声明过,则属于对变量 ...

  4. MYSQL复习笔记5-select-from-where子句

    Date: 20140125Auth: Jin参考:http://dev.mysql.com/doc/refman/5.1/zh/sql-syntax.html#select一.select子句主要定 ...

  5. JavaScript基础入门教程(四)

    说明 前面三篇博客介绍了js中基本的知识点,包括变量类型及其转换.表达式.运算符等小知识点,这篇博客主要讲的是对象.如果你学过java等语言,你也许在下文的阅读中发现在js中的对象与java中的对象存 ...

  6. 【spring cloud】spring cloud分布式服务eureka启动时报错:java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApplicationBuilder.<init>([Ljava/lang/Object;)V

    spring cloud分布式服务eureka启动时报错:java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApp ...

  7. Bestreviewapp给iOS软件写评论赚钱

    BestReviewApp 这是一个评论类的活动,网站上会提供App列表,在iTunes评论这些应用就能获得报酬.目前账号中的余额可通过PayPal或支付宝提取出来.BestReviewApp 开放的 ...

  8. 公司机器(线上机器)启动ftp任务的命令

    这个命令: /usr/local/proftp/sbin/proftpd 注意要在root账户,并且kill掉原来的同名进程.

  9. MySQL删除表的时候忽略外键约束

    删除表不是特别常用,特别是对于存在外键关联的表,删除更得小心.但是在开发过程中,发现Schema设计的有问题而且要删除现有的数据库中所有的表来重新创建也是常有的事情:另外在测试的时候,也有需要重新创建 ...

  10. 用Markdown写博客快速入门

    Markdown,简单来说,就是一种可以方便转换为HTML的带标记符号纯文本. 它是对我等键盘党的福音:我不用再费劲挪动鼠标去按加粗.设置段落了,用键盘输入所有文本,一气呵成. 最重要的是,cnblo ...