c++ 左值和右值以及左值引用和右值引用

何为左值和右值?

对于左值和右值,在表现形式上来看,就是赋值语句中,等号右边的就是右值,等号左边的就是左值

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(){...}
//即可!!

看似好像这个没有多大用处,但我真的为了建一棵树被这个折磨了整整三天!!!

posted on 2020-06-15 21:35  The0Y  阅读(494)  评论(2编辑  收藏  举报

导航