左值右值大体上可以看做是在 =赋值运算符 左边还是右边的值。
如果是左值,表示他可以放在 = 左边,也就是可以给他赋值。
如果是右值,表示他不可以放在 = 左边,也就是不可以给他赋值。
注意 左值右值并不是只能放在左边或者右边 左值也可以放在 = 右边。
为什么会造成某些值可以在 = 左边 某些只能在 = 右边呢?
主要在与表达式结束后还有没有一个在内存中仍然存在可以改变的非临时的对象,如果存在,则可以给这个内存赋值,如果不存在,则不可以赋值,这就造成了左值右值
左值右值不是针对变量来说的,而是针对表达式来说的,比如 a+b a==b a++ ++a 。
那么哪些是左值:
左值是表达式最终结束后仍然存在的对象
左值可以看做用&操作符可以获得地址的
因为表达式结束后仍然存在,所以他在内存中是有一个持久的地址的,所以可以给左值赋值 lvalue = value 因为内存中有地址,所以赋值操作成立
比如 a = a+b 最终表达式仍然存在一个变量a 在内存中有地址,所以此为左值
++var: 首先对变量var所在的地址存放的值+1 然后返回这个变量,也就是说内存地址并没有改变。
哪些是右值:
表达式结束后不存在对象
用&操作符不可以获得地址
比如 123 这是个整数常量 在内存中有地址吗? 没有,所以这是右值
比如123+456 这是右值
比如"aaa" 在内存中有地址,但是这个地址可以改变吗? 字符串常量存放在常量区,是不可以改变的,也就是不可以被赋值 这是右值。
那么 a++ 是左值还是右值?
分析: 这个表达式共有两步:
1. int tmp = a;
2. a++
第一步产生一个临时量tmp 以这个临时量作为操作使进行操作,然后再对a这个变量++ 以此达到先使用再递增的策略
所以 a++ = 123 这个表达式实际上是对一个临时量tmp进行赋值,而临时量系统很快就给他收回,即使对他赋值也无济于事,所以系统规定临时量是一个右值。
那么函数调用时,func()是左值右值??
分析:还是看这个函数的返回值有没有可变非临时对象。
如果func()的原型是 int func(); 那么他返回一个临时量 临时量是右值,所以func()也是右值 也就是说 func()=100 不能编译通过
如果func()的原型是 int& func(); 那么他返回的是一个引用,此时还分两种情况
1.返回的引用是函数内的局部变量:函数结束局部变量立刻销毁,所以是临时对象,此时为右值
2.返回的引用是在这个函数体外的变量,此时返回的不会立刻销毁而且可以改变,此时为左值 func() = 100 可以通过
总之:
左值右值可以简单看做可以放在 = 左边或者不能放在左边
a++ 和 ++a 不同
临时量是右值
只有一种情况的func() 函数可以作为左值