理解lvalues和rvalues在c/c++

在看 Eli Bendersky的文章的时候,记录一下。

引言

左值和右值在编程中不是常遇见,但出现时候,不能很快理解,所以这次做一个总结。

int foo()
{return 2; }
int main()
{ 
foo()=2;
return 0;
}

gcc编译这段代码

cpp error: lvalue required as left operand of assignment
foo()=2; 左值需要一个左运算符

再用g++编译

int& foo(){return 2;}

错误,右值错误。

定义

1,定义一个左值:表示在存储器中占用一些可识别的内存空间的对象。
2,右值用排除法来定义,每个表达式都是左值,否则是右值。所以知道rvalue是一个表达式,不表示对象,不再内存占可标识的位置空间

例子

int var;
var=4;

一个赋值操作,期望一个左值是左操作数,var就是一个左值(在存储器中占可标识的空间)。
下面这个就是错误的:

4=var;			//wrong
(var+1=4//wrong

因为,对于4和(var+1),他们都不是左值(不在存储器中占可标识的空间),那么他们就成了右值(在计算期间仅驻留某个临时存储器中)都是表达式的临时结果,没有可识别的存储位置。
现在知道了第一段代码为什么错误了,因为foo函数返回了一个临时值,一个右值,foo()=2在编译器期望他应该是一个左值,能够被2赋值!
但是,并不是对所有的函数返回值调用分配都是无效的,c++的引用使得有可能
如:
int globalvar=20; int &foo(){ return globalvar; } int main() {foo()=10 ; return 0}注意:此处foo返回一个引用,他是一个lvalue。
对于c++返回左值的能力多用于重载某些运算符。常见用例是在重载方括号运算符 “[ ]” 时,如:

std::map<int, float> mymap;
mymap[10]=5.5;

在这里将5.5赋值给mymap[10]起作用是因为std::map::operator [] 的非常量的重载返回引用。

可修改的左值

c定义的时候,是:适用于赋值左侧的值。但是在引入const关键字后,由const定义的左值变得不可修改了。
const int a=10;
a=4; //无法分配修改了

左值和右值之间的转换

一般,对对象的值进行操作的语言在构造时候都需要使用右值(不再存储器中占可标识空间的值,将亡值)作为参数。如“+”将两个右值作为参数,返回一个右值最后赋值给左值。

int a=1;
int b=2;		//a,b是左值
int c=a+b;	//+需要右值,所以将ab转换成右值,并返回右值

上述进行了隐式的转换,左值——》右值
反过来呢?、将右值转换为左值。但是必须要显示地分配。绝对不可能隐式的转换右值变为左值。
使用“ * ”解引用运算符可以产生左值,将右值作为参数

int arr[]={1,2};
int * p= &arr[0];		//&将左值变成右值
* (p+1)=10;	//正确,P+1是一个右值,但是*(p+1)是一个左值。

显式转换。
注意:“ &” 运算符取地址,采用的是左值作为参数!!!所以参数不能输入右值
如:

int var=10;
int * bad_addr=&(var+1);	//这是明显错误的,因为&参数只能是左值,才能转换为右值。
正确做法:
int *p=&var;
错误:
&var=38//&var 是一个右值!

这只是左值右值的冰山一角,还有很多值得去学习的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值