c/c++中的lvaues(左值)跟rvalues(右值)

c/c++中的lvaues(左值)和rvalues(右值)

1.1        写在开头

也许有朋友看到这个介绍,会一笑而过。认为,Lvaues不就是,出现在赋值运算符“=”左边的表达式么,相应的rvalues不就是出现在赋值运算符“=”右边的部分么,这有啥难的呢?

hand一下!其实在写这篇文章之前,我和你的想法一样。平时看资料,调试代码的时候,经常遇到lvaues和rvalues这两个词。并且每次看到都认为是很简单,不重要的东西,所以都略过,更谈不上深究。但,老是感觉很别扭,既然这么简单的东西,为什么在技术资料中作为术语呢?并且编译器报错,也提到这两个词呢?

今天找了一些资料,仔细学习了一下,才知道,之前的理解也是没有错。不过,仅仅是表面文字理解,没有抓住本质而已。

1.2        定义

Ø  lvaues本质“就是指一些对象、或者是表达式。这些对象、表达式必须代表一块内存区域”。换句话说,lvaues就是代表一块内存区域的对象(object)或者是表达式(expression)。

Ø  Lvaues,有“可修改”和“不可修改”之分。

例如:

可修改的lvaues:

Int *p;

Int n;

std::string& student_name();

 

不可修改的lvaues(一般都是常量对象):

const std::stringname;

 

Ø  rvalues 被定义为“除了lvaues以为的所有对象、或者表达式”。其实,本质是“不能表示一块内存区域”。

总结:

1、  当需要保存数据的时候,需要lvalues。

2、  当需要读取数据的时候,需要rvalues。

1.3        举例

1、  literal const(字面常量)是rvalues,例如:1,27.8,“hello world”

2、  临时对象是rvalues,因为临时对象的生命周期比较短,所以不建议修改临时对象。故,把它作为rvalues。例如:std::string(“hello world”);

补充:临时对象可以调用对象的“非const类型的成员函数”。但是,临时对象不能传递给“函数的非const类型的引用参数”。

我想这样做的目的是:当临时对象调用“非const类型成员函数”的时候,生命周期是可以控制的,所以是允许的。但是,把临时对象作为“函数的非const类型的引用参数”传递下去,无法预测函数调用栈内部会做什么操作,修改临时对象,会带来不可预测的灾难。

3、  数组名称是rvalues。例如 ,int vector[12]。

也有人认为,数组名称是“不可修改的lvaues”。但是笔者认为“数组名称代表一块连续内存区域的地址,这个地址在编译的时候是一个具体的数值,是不可修改的,所以认为是rvalues”

4、  函数非引用类型返回值是rvalues。例如,intget_count();

5、  取地址运算符&, 要求一个lvaues操作数,但是产生的结果是rvalues。例如,

int a;

&a = 1;//error,&a是一个rvalues

&22//error,&运算符需要一个lvaues操作数

6、  提领运算符*, 结果是一个lvaues。例如,int a;int *p = &a; *p = 22;

7、  前置++运算符,需要一个lvaues操作数,产生的结果是一个lvaues,例如,

int a;

++a = 32;

所以,前置++运算符重载函数的返回值类型是引用类型

_Mytype& operator++()

      {  // preincrement

      _Inc();

      return (*this);

   }

8、  后置++运算符,需要一个lvaues,产生的结果是一个rvalues,例如,

int a;

a++ = 44;//error , a++的结果是rvalues

所以,后置++运算符重载函数的返回值类型是值类型

_Mytype operator++(int)

      {  // postincrement

      _Mytype _Tmp = *this;

      ++*this;

      return (_Tmp);

   }

9、= += -= *= %=<<= >>= &= ^= |= 等运算符的左操作数必须是lvalues

 

1.4        lvalues和rvalues角色的相互转换

1、  根据表达式的上下文情况,lvalues在需要rvalues的地方会自动转换为rvalues。例如,

int n;

int m;

m = n+2;//这个表达式里n是rvalues

2、  rvalues永远不能转换为lvalues

参考:

1、http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Flvalue.htm

2、http://www.codeproject.com/Articles/313469/The-Notion-of-Lvalues-and-Rvalues

3、http://en.wikipedia.org/wiki/Value_(computer_science)