左右值及其引用详解

文章目录


一、左值和右值

一段内存有两个基本的属性:内存的地址和内存中存储的数据。而左值(L-values)和右值(R-values)就体现了这两种感觉。从字面意思来看,左值就是=左边的值,右值就是=右边的值。这也可以浅显的得出,C++中的表达式不是左值就是右值,绝无出二者之外,但表达式可以同时具有左值属性和右值属性。左值表达式的特点是有持久性,可以取地址,可以被我们赋值,也就是说具有可以被我们访问的存储单元,例如变量、对象成员等。而右值的特点是通常的临时性,无法被我们修改。列如常量、可以是不占据内存的临时变量或字面值,可以是不具有写入权限的空间实体等。因此,我们可以用赋值运算符(=),取地址符(&)来判断表达式是左值还是右值,如果可以使用就是左值,否则为右值。同时,左值表达式的整体应是一个对象,但表达式整体是一个对象的表达式不一定是个左值。

二、引用

在C++11引入了右值引用的概念之后,我们可以将引用分为三种了,也就是左值引用和右值引用,以及常量引用(其实也是左值引用的一种)。

右值引用就是绑定到右值上的引用。右值引用可以说是针对临时对象的,与左值引用相对。

右值引用的主要作用是消除两个对象间不必要的拷贝,移动含有不能共享资源的类对象,提升效率。

右值引用使用 && 符。使用&&绑定右值的右值引用是可以取地址和赋值的,也就是说右值引用是左值。

cpp 复制代码
int &&ra=1;//ra为右值引用,但为左值
ra=3;//赋值操作
int *b=&la;//取地址操作
//以上操作都是正确的

引用并不可以像指针那样可以指向一个空指针,并没有空引用的概念,所以引用在定义时必须进行初始化。常量引用是左值引用中的极其特殊的一部分,因为常量引用可以绑定到右值上。当我们将一个左值绑定到常量引用的时候,编译器会生成一个临时变量去接收左值的值,再将其绑定到常量引用上,这样就实现了常量引用绑定右值。总结一般来说,左值引用只能绑定左值,右值引用只能绑定右值,常量引用都可以绑。(这里左值引用指非常量左值引用)。

返回左值引用的函数以及赋值、下标和前值递增递减运算符(前++,前--)都是返回左值的例子。返回非引用类型的函数以及算数、关系、位和后置递增递减运算符(后++,后--)都是返回右值的例子。前++/--实际上是将内存中的数据减/加1,而后++/--则会产生产生一个临时变量用于接表达式的值并减/加1,当使用完后,临时变量就会销毁。

对于左值引用和右值引用,我的理解是,左值引用是内存地址和内存内容的双重绑定,而右值引用更像简单的绑定内容,或者更干脆的将临时对象起个名字,将其变为一片持久的内存地址(这种给人一种二次利用的感觉,就好像是房东将即将到期出租房改为商品房把房产证转让了)。

三、std::move函数

我感觉这里move的意思是从左边移动到右边吧,因为std::move的作用就是把左值强制转换为右值。如果我们再用一个右值引用来接std::move返回的右值,那么我们实现了对象权限或者状态之间的转换,这种转换并不会开辟新的内存或者调用拷贝操作,是极其高效的。一般来说,我们不会对还回再次使用的对象使用std::move操作,也不会滥用它。

cpp 复制代码
int &&a=10;
int &&b=std::move(a);
相关推荐
StrokeAce1 小时前
linux桌面软件(wps)内嵌到主窗口后的关闭问题
linux·c++·qt·wps·窗口内嵌
一颗花生米。2 小时前
深入理解JavaScript 的原型继承
java·开发语言·javascript·原型模式
问道飞鱼2 小时前
Java基础-单例模式的实现
java·开发语言·单例模式
学习使我快乐012 小时前
JS进阶 3——深入面向对象、原型
开发语言·前端·javascript
通信仿真实验室3 小时前
(10)MATLAB莱斯(Rician)衰落信道仿真1
开发语言·matlab
勿语&3 小时前
Element-UI Plus 暗黑主题切换及自定义主题色
开发语言·javascript·ui
家有狸花4 小时前
VSCODE驯服日记(三):配置C++环境
c++·ide·vscode
dengqingrui1235 小时前
【树形DP】AT_dp_p Independent Set 题解
c++·学习·算法·深度优先·图论·dp
C++忠实粉丝5 小时前
前缀和(8)_矩阵区域和
数据结构·c++·线性代数·算法·矩阵
我的心永远是冰冰哒5 小时前
ad.concat()学习
学习