c++左值右值解释
现在网上对于左值右值的解释很多废话
什么是左值和右值
左值就是有指向特定内存地址的变量,反之就是右值;
而且左值一般出现在等号左边,右值一般出现在等号右边
最简单的
int x = 666; // ok
上面的x是左值,666是右值;因为x是一个变量,运行的时候给x分配了内存,x是有地址的,一个有地址的变量就是左值,而666是一个常量,是一个右值。
然后对于左值,不一定都放在等号左边,例如:
int *y=&x; //ok
我们看上面,x作为一个左值出现在了右边,y是一个指针变量,存放地址,而x也是一个变量,但是使用取地址符&之后得到的是x的地址,地址是一个常量,也就是说&x是一个右值,所以上式成立
所以上面两个都是正确使用左值右值的例子,下面这个则是错误的例子
int y;
666 = y; // error!
原因不难看出666是个右值,y是左值,以上代码在gcc运行时会出现如下错误提示:
error: lvalue required as left operand of assignment
下面这个操作也是错的
int *y=&666; //error
对一个常量取地址是不存在的,取地址符只能对一个左值操作
这个在gcc中的错误提示:
error: lvalue required as unary ‘&’ operand`
&地址符需要一个左值
方法返回左值和右值
等号左边一般是左值,所以下面这个操作是错误的:
int setValue()
{
return 6;
}
setValue() = 3; // error
返回的6是个右值,不能作为左值使用
但是如果改为以下写法,那就是正确的:
int global = 100;
int& setGlobal()
{
return global;
}
setGlobal() = 400; // OK
这里的setGlobal返回的是一个引用,引用是指向一个有效地址的,属于左值,所以以上操作合理,注意区分取地址符和引用
左值到右值的转换
有时候我们会看见左值也出现在等号右边,除了取地址符外,还有以下情况:
int x = 1;
int y = 3;
int z = x + y; // ok
这里x和y作为左值居然在等号右边,但是也合理,是因为这里做了一个隐式转换。还有很多的其他运算会进行隐式转换,如减法、乘法、除法。
左值引用
常见的引用使用方式如下:
int y = 10;
int& yref = y;
yref++; // y is now 11
这里的y和yref都是左值,为什么可以这样呢,这是因为c++编译器规定非常量引用的变量初始值必须为左值,所以下面的操作是错误的:
int& yref = 10;
10是右值,不能用来初始化引用,但是如果是常量引用的话,就合理了
const int& yref=10;
如果忽略这个知识点,很容易在给函数参数赋值的时候出现错误
void fnc(int& x)
{
}
int main()
{
fnc(10); // Nope!
// This works instead:
// int x = 10;
// fnc(x);
}
void fnc(const int& x)
{
}
int main()
{
fnc(10); // OK!
}
而对于常量引用的底层实际上隐式定义了一个临时的变量
const int& ref = 10;
//相当于
int __internal_unique_name = 10;
const int& ref = __internal_unique_name;