对于左值和右值,在表现形式上来看,就是赋值语句中,等号右边的就是右值,等号左边的就是左值
int y=666;//OK
在这个语句中,666就是右值,y就是左值
int y; 666=y // error!
这个时候就会报错 赋值语句左边必须是可修改的左值
可见 左值是必须可修改的
int *y; int x; y=&x; //OK y=&666 //error!
可见左值是可以取地址的
哦对了 忘记声明一点 ,引用的右边必须为左值
int x; int &y=x; //OK int &y=666; //error!
这个其实也比较好理解(一个常量哪来的地址哇)
那么,一个函数的返回值,是左值还是右值呢?
其实我们仔细想想也知道,当然是右值啦,我们只有把一个函数返回值赋予给一个变量输出,哪有给一个函
数赋值的说法!
但其实有时候 以下的情况
#include<iostream> using namespace std; int i = 3; int j = 4; int* p; int * test() { p = &i; return p; } void f(int*& q) { *q = j; } int main() { f(test()); //error! cout << i; //i=4 }
让我来解读一下
函数test()返回一个指向i的指针p
函数f()接收这个指针,并用指针q作为指针p的引用
然后让指针q所指向的内容变为j
q是p的引用 此时p指向的内容变为j
p指向i,所以i的值变为j
看上去是完美的不行但是!!
回到问题—>函数返回的是一个右值,又怎么能让它放在引用的右边呢?
1. 右值引用法
我们之前学过的所有引用都是左值引用,也就是引用的右边是一个左值,其实还有右值引用,而右值引用本来没有什么实际意义,但在函数返回值这,它就发挥了关键作用。
int &&p=3;
阿这 那你告诉我这样有什么用呢...p是3的引用?为啥我不直接给p赋值3!!
好了好了 那么上面的代码我们只需
void f(int *&q){...} //改为 void f(int * &&q){...} //即可!!
2. 把函数返回值”转变为“左值
其实有一个很巧妙的方法,也是最常用的方法,让我们的函数返回值“变成”一个左值!
怎么操作呢?那就是引用
我们只需要让函数的返回值用一个引用接收即可,这就把函数的返回值从右值“转变为“左值,当然这并不是函数的返回值,只是函数返回值的引用,所以函数的返回值还是右值,只是我们用引用接收它变成了左值,就可以传给其他的引用啦。
int &f() //注意,这个&不是取地址! 是引用 { return 3; } int f()=400; //不会报错 但没有什么实际意义
那么我们上面的代码就可以变更
int * test(){...} //改为 int *& test(){...} //即可!!
看似好像这个没有多大用处,但我真的为了建一棵树被这个折磨了整整三天!!!
原文:https://www.cnblogs.com/yuuuuu422/p/13138042.html