左右值及其引用详解

文章目录


一、左值和右值

一段内存有两个基本的属性:内存的地址和内存中存储的数据。而左值(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);
相关推荐
霸王蟹4 分钟前
常见面试题:Webpack的构建流程简单说一下。
前端·笔记·学习·webpack·node.js·vue
qq_584598926 分钟前
day30python打卡
开发语言·人工智能·python·算法·机器学习
zhangpeng4555479407 分钟前
C++--综合应用-演讲比赛项目
开发语言·c++·算法
火兮明兮17 分钟前
Python训练第三十天
开发语言·python
啊我不会诶20 分钟前
CF每日4题(1300-1400)
开发语言·c++·算法
freyazzr30 分钟前
Leetcode刷题 | Day64_图论09_dijkstra算法
数据结构·c++·算法·leetcode·图论
学编程的小白狼33 分钟前
C#:多线程
开发语言·c#
island131434 分钟前
JAVA Web 期末速成
java·开发语言·前端
MVP-curry-萌神35 分钟前
FPGA学习知识(汇总)
学习·fpga开发
珊瑚里的鱼39 分钟前
【滑动窗口】LeetCode 1004题解 | 最大连续1的个数 Ⅲ
开发语言·c++·笔记·算法·leetcode