在C++中经常会听到左值与右值的称呼,每次都没有太注意,正好今天仔细的查阅了一下资料,并且自己试着写了写程序,发现有些文章写的确实有点问题,在此表达一下自己的想法。
左值与右值并不是通常讲的在操作符左边就是左值,在操作符右边就是右值,这是错误的。左值与右值是针对表达式而言的。通俗的解释一下,左值就是能去地址,右值就是只能取值的。左值是长久存在的对象,右值是临时的对象。C++中对象的准确定义是:指向内存中一块固定区域。比如:
int a = 5;
这里的a实际上就是变量名称,而a指向的内存的区域才是对象,就等于把对象和变量绑定到一起了。下面举一些例子来讲解左值与右值;
最常见的就是对a++和++a的误解,有些文章说两者都是右值而不能做左值,这 其实是错误的。
当执行a++命令时,首先产生一个临时对象,将a赋给该临时对象,然后修改a执行a+1的操作,这样返回的其实是临时变量,因此不能取地址,所以a++一定是右值而不是左值;
再来看++a,当执行++a命令时,首先对a执行a+1的操作,然后将a+1返回,所以可以取地址,于是++a可以是左值。下面程序是可以执行的:
int a =0;
int b=2;
++a = b;
此时的结果中,a=2;证明了++a可以为左值。
下面介绍其他的例子:
int a = 1;
int b = 2;
int* p = &b;
vector<string>s;
s.push_back("Hello");
string str = "World";
const char &q = 'a';
在上述代码中,我们一句一句来分析。
a可以取地址,并且持久,是左值;1不能取地址是右值;同样的道理b是左值,2是右值;加入我们现在有a+b的操作,很明显这是一个临时对象,不能取地址,所以是右值。
字符串类型容器s,如果调用了是s[0]的话,因为返回的string&,所以是左值;str可以去地址,是左值;q也是左值;还有函数的返回值也只能作为右值。
c++不仅有左值和右值还有左引用和右引用,其中右引用很好的解决了临时对象导致程序执行效率差的问题。
其中引用分为:非常量左值引用、常量左值引用、非常量右值引用还有常量右值引用。
非常量左值引用只能绑定到非常量左值,这个应该比较容易理解,如果绑定到常量类型,很明显修改常量已经违背了常量的含义;如果绑定到非常量右值并且使用时,有可能使用的是已经销毁的临时对象,这是很危险的;而常量左值可以绑定到所有类型。