左右值及其引用详解

文章目录


一、左值和右值

一段内存有两个基本的属性:内存的地址和内存中存储的数据。而左值(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 小时前
02Numpy基础(上)
开发语言·python
TheBestRucy4 小时前
Python 九阳神功之贰:面向对象(下)
开发语言·python
吃着火锅x唱着歌5 小时前
Effective C++ 学习笔记 条款43 学习处理模板化基类内的名称
c++·笔记·学习
AI_小站5 小时前
刚面完百度的 Agent 开发岗,我才发现:世界就是个巨大的草台班子
java·开发语言·人工智能·spring·百度·langchain
felixking6 小时前
C++20 协程
开发语言·c++·协程
weixin_431600446 小时前
Agent Workflow 学习向:Code 节点,比模板更强的变量加工
后端·python·学习·ai·
Xuanzang Road7 小时前
第 40 届学习强企玄奘路戈壁挑战赛:在绝境中重塑自我
学习
Zane1994127 小时前
CAS 与原子类:Java 如何实现无锁编程
java·开发语言
码农颜8 小时前
6.3 主函数流程剖析
开发语言·php
tju新生代魔迷8 小时前
Python学习日记3
学习