左右值及其引用详解

文章目录


一、左值和右值

一段内存有两个基本的属性:内存的地址和内存中存储的数据。而左值(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);
相关推荐
_.Switch几秒前
Python 自动化运维持续优化与性能调优
运维·开发语言·python·缓存·自动化·运维开发
徐*红1 分钟前
java 线程池
java·开发语言
尚学教辅学习资料1 分钟前
基于SSM的养老院管理系统+LW示例参考
java·开发语言·java毕设·养老院
1 9 J3 分钟前
Java 上机实践4(类与对象)
java·开发语言·算法
Code apprenticeship4 分钟前
Java面试题(2)
java·开发语言
J不A秃V头A7 分钟前
Python爬虫:获取国家货币编码、货币名称
开发语言·爬虫·python
懒惰的bit2 小时前
基础网络安全知识
学习·web安全·1024程序员节
SRY122404193 小时前
javaSE面试题
java·开发语言·面试
李元豪3 小时前
【智鹿空间】c++实现了一个简单的链表数据结构 MyList,其中包含基本的 Get 和 Modify 操作,
数据结构·c++·链表
无尽的大道3 小时前
Java 泛型详解:参数化类型的强大之处
java·开发语言