C++: 左值引用和右值引用

news2024/10/5 10:10:35

目录

概念:

理解:

 左值引用,右值引用

 左值引用能否给右值取别名?

右值引用能否给左值取别名?

引用的意义是什么?

左值和右值对自定义类型有什么区别吗?

move的妙用!

没有优化的左值传输:

 临时变量是必然产生的!

 右值引用本身是左值!

主要原因:

右值引用的底层 和左值引用的底层: 

右值能否被改变?

概念:

传统的C++语法中就有引用的语法,而C++11中新增了的右值引用语法特性,所以从现在开始我们 之前学习的引用就叫做左值引用。无论左值引用还是右值引用,都是给对象取别名。

什么是左值?什么是左值引用?

左值是一个表示数据的表达式(如变量名或解引用的指针),我们可以获取它的地址+可以对它赋 值,左值可以出现赋值符号的左边,右值不能出现在赋值符号左边。

定义时const修饰符后的左 值,不能给他赋值,但是可以取它的地址。

左值引用就是给左值的引用,给左值取别名。

int main()
{

// 以下的p、b、c、*p都是左值
int* p = new int(0);

int b = 1;

const int c = 2;

// 以下几个都是常见的右值
10;

x + y;

fmin(x, y);

return 0;

}

理解:

在以往较为浅薄的理解中,左值是可以进行修改的,右值是无法进行修改的

例如,图中的a是变量可以进行修改是左值,但10是常数不能进行修改是右值,但不完全是这样的结果:又如下图所示,a在第一行代码中是左值,在第二行代码中又充当了右值,所以左值和右值不能如此轻易的划分。

又如:加上了const的c是不允许被修改的,所以c是左值还是右值?答案是:c是左值!

因此,最后我们可以总结出一个结论, 可以取地址的是左值,不能取地址的是右值。

同时我们也需要注意,左值代表的不一定是一个数值,也可也是一个表达式。

例如:

*p 
*p 是一个左值

vector<int> v(10,1);
v[1];
v[1] 是一个左值

凡是能取到地址的都算是左值! 

而右值就是取不到地址的,同样右值也可以是一个表达式,且同时,临时变量、匿名对象、临时对象统统都是右值!

都是右值 

 左值引用,右值引用

引用就是取别名!左值引用就是给左值取别名,右值引用取别名!

int main()
{



// 以下的p、b、c、*p都是左值
int* p = new int(0);

int b = 1;

const int c = 2;

// 以下几个是对上面左值的左值引用

int*& rp = p;

int& rb = b;

const int& rc = c;

int& pvalue = *p;


double x = 1.1, y = 2.2;
// 以下几个都是常见的右值
10;

x + y;

fmin(x, y);
// 以下几个都是对右值的右值引用

int&& rr1 = 10;

double&& rr2 = x + y;

double&& rr3 = fmin(x, y);
// 这里编译会报错:error C2106: “=”: 左操作数必须为左值

10 = 1;

x + y = 1;

fmin(x, y) = 1;

return 0;
}

 左值引用能否给右值取别名?

答案是不可以!但是加上const可以!

右值引用能否给左值取别名?

答案也是不可以!但是需要把左值加上move进行使用后才行!

所以左右值引用 可以对左右值进行取别名,但是要有条件!

引用的意义是什么?

  • 减少拷贝!提高效率!传值、传参、传引用返回 都可以使用引用,这是左值引用的常见场景!
  • 但是左值引用没有彻底解决返回值的问题,右值引用就是修补这一块内容。
  • 因为如果是一个临时对象,或者局部对象,则不能使用引用返回!因为出了作用域地址就会被销毁,所以没有用!而这种问题也不能直接使用右值引用进行返回,右值引用返回不是这样用的! 

例如:

在主函数调用的时候,会在返回的时候进行临时变量的构造然后再加上拷贝构造把数值从临时变量中进行拷贝导赋值变量中,然后C++11后面优化成了一个直接获取!

 这里无论是加左值引用还是右值引用都没有效果且会报错,因为str是局部变量被销毁了!地址不存在了!因为出作用域了!

为了解决这种问题,增加一个右值引用的构造函数,而被右值引用修饰的构造叫做移动构造!

有了移动构造,编译器会进行选择,如果返回的时候是左值,那么编译器就会去选择拷贝构造,如果是右值,那么就会 选择移动构造

左值和右值对自定义类型有什么区别吗?

自定义类型的右值基本都是匿名对象、传值返回的临时对象。

然后右值又有细分,分为纯右值和将亡值,基本上内置类型的右值都是纯右值,而自定义类型的右值基本都是将亡值。

对于局部变量来说,它的左值只能是老实的开辟空间然后被利用完被拷贝完后销毁空间,

而对于局部变量来说,它的右值(将亡值),它会利用空间! 将拷贝数值的空间和临时变量的空间进行交换!

 有了移动构造后,在传值时,会强行把左值变成右值,强行使用了move (可以不在返回时加上move 编译器会做处理!)/可以看出str虽然是左值,但是和将亡值没什么区别

 然后会调用两次移动构造,但是编译器直接转移资源,一步到位!以前需要进行拷贝,但是右值的移动构造,将被赋值的数值强行和右值进行交换!

移动构造为什么叫移动构造,是因为它移动将亡值对象的资源!!!!把将亡值的资源转移到被赋值调用的数据上!

严格来说,移动构造是延长了将亡值 所占据的资源数据的生命周期,而不是延长了将亡值所处在空间地址的生命周期。因为是转移资源,所以移动构造的代价是极低的!

move的妙用!

可以看出s1的数据被移动到了s3 这就是move的功能!  

没有优化的左值传输:

没有优化的传输其实就是仙拷贝构造在赋值拷贝,就如下图中的写法,导致编译器无法进行优化!

 优化:进行优化的左值传输!一次构造和一次拷贝构造,最后被编译器优化成了一次拷贝构造!

 临时变量是必然产生的!

 临时对象是必然产生的,这个临时对象是在寄存器的,但是寄存器非常的小,所以当对象数据过大时,会把临时对象放到两个数据的栈帧中:如下图所示的绿色框框就是处在main和to_string两个栈帧之间!

这种编译器无法进行优化的,可以使用move进行转化成移动构造函数,将其变成一次移动构造,一次移动赋值!

str在传输时会给一个临时对象,然后把临时对象的数据(空)的数据和 传输的数据进行数据之间的交换,然后在临时赋值的时候,因为在赋值之前进行初始化,所以会把初始化的那个空间和临时对象内部的数据再一次进行交换,然后完成移动赋值!

 右值引用本身是左值!

右值和右值引用,求s1是右值还是左值?左值!已知std::string(“11111111”)是右值

但是右值引用是左值!有地址!右值引用本身是左值!

主要原因:

右值有一个特点,本身是不能改变的,因为如果使用了别名,那如果别名也不能改变,那如何做资源转移?

可以看出右值的资源转移主要是因为swap如转移的过程中数值不能进行改变,也就是右值引用的数据不能改变,那么将无法进行资源的转移!所以也就可以得出,右值引用是左值!

右值引用的底层 和左值引用的底层: 

右值引用和左值引用的底层都是指针,都是取匿名空间的地址!所以右值真的没有地址吗?那右值存哪里?总要存储吧!所以右值是有地址的,只是不能拿取这个地址罢了!取不到这个地址罢了! 

右值能否被改变?

s5是可以左值引用s1的!但是s6是不能直接左值引用的!但是可以使用强制转化:

可以资源转移到s7!所以右值能否改变呢!可以的!如果不用强转呢?

先给一个右值引用,然后在左值引用,本质就是右值引用底层是指针,且底层还是有空间存储的!

和上面的s5和s1的操作一样!类似于交换!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1889963.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringMVC常见的注解

一、Spring MVC Spring Web MVC是基于ServletAPI构建的原始web 框架&#xff0c;一开始就包含在Spring 框架中&#xff0c;通常被称为“Spring MVC”。 1.MVC 是什么&#xff1f; MVC(Model、View、Controller&#xff09;是软件工程中的一种软件架构设计模型。它把软件系统分…

力扣hot100-普通数组2

文章目录 题目&#xff1a;轮转数组方法1-使用额外的数组方法2-三次反转数组 除自身以外数组的乘积方法1-用到了除法方法2-前后缀乘积法 题目&#xff1a;轮转数组 原题链接&#xff1a;轮转数组 方法1-使用额外的数组 方法1是自己写出来的。方法2参考的别人的&#xff0c;…

transformer模型学习路线_transformer训练用的模型

Transformer学习路线 完全不懂transformer&#xff0c;最近小白来入门一下&#xff0c;下面就是本菜鸟学习路线。Transformer和CNN是两个分支&#xff01;&#xff01;因此要分开学习 Transformer是一个Seq2seq模型&#xff0c;而Seq2seq模型用到了self-attention机制&#xf…

tinyshop项目部署

参考软件测试之测试用例设计&#xff08;四&#xff09;_管理后台 测试用例-CSDN博客 1、下载xampp 2、修改apache和mysql的端口分别为4431 &#xff0c;8013和3306 3、访问页面&#xff1a;输入ip:端口号&#xff0c;出现以下页面即成功 4、安装tinyshop商城 将解压的tinys…

苹果手机数据被抹除了怎么恢复?学会这招就够了

数据丢失&#xff0c;是每一个iOS用户都有可能会遇到的问题&#xff0c;尤其是因为操作不当不小心抹除了数据&#xff0c;这个问题会变得更加糟糕&#xff0c;因为 iPhone中的数据、设置、下载的软件等内容都会被清除掉。那么iphone抹掉数据后怎么恢复&#xff1f;本文提供了相…

VMware虚拟机Ubuntu网络有线线缆已拔出问题

1、问题描述 VMware虚拟机Ubuntu不能联网&#xff0c;打开设置中&#xff0c;网络显示“有线 线缆已拔出”。 2、查看虚拟网络连接 查看主机的网络连接&#xff0c;确保虚拟网络已启用。 3、启动虚拟机网络服务 打开主机的 ‘服务’&#xff08;winr&#xff0c;运行框中输入…

视频监控平台LntonCVS视频监控汇聚平台技术优势分析

安防视频管理系统LntonCVS视频智能汇聚融合平台&#xff0c;是一款功能强大的视频管理平台&#xff0c;支持多种操作系统包括Windows、Linux&#xff08;CentOS、Ubuntu&#xff09;和国产化系统。该平台能够通过多协议接入&#xff0c;并利用视频应用引擎将多种格式的视频数据…

ABAP OO面向对象编程--定义、实现和使用类

- Define, implement and use simple class&#xff08;定义、实现和使用简单类&#xff09;&#xff1a;指的是在编程中创建一个基本的类&#xff0c;实现其功能&#xff0c;并在程序中使用它。 类是对象的模板。反过来说&#xff0c;也可以说对象的类型就是它的类。类是对对象…

聊一聊领域驱动和贫血

写在前面 前段时间跟领导讨论技术债概念时不可避免地提到了代码的质量&#xff0c;而影响代码质量的因素向来都不是单一的&#xff0c;诸如项目因素、管理因素、技术选型、人员素质等等&#xff0c;因为是技术债务&#xff0c;自然就从技术角度来分析&#xff0c;单纯从技术角…

秋招Java后端开发冲刺——非关系型数据库篇(MongoDB)

MongoDB 本文介绍非关系型数据库MongoDB的基础知识和常见面试题。 &#xff08;一&#xff09;基础知识 1. 介绍&#xff1a;MongoDB是一个基于分布式文件存储的数据库&#xff0c;由C语言编写&#xff0c;旨在为WEB应用提供可扩展的高性能数据存储解决方案。 2.特点 特点…

数次同台,极越与小米的爱恨情仇

在汽车行业&#xff0c;提起小米&#xff0c;或许很多人都会记得在北京车展登台亮相的小米su7。可提到极越&#xff0c;或许更多人会为之一愣——这是个什么汽车品牌&#xff1f; 实际上&#xff0c;在今年四月的北京车展中&#xff0c;它就坐落于小米汽车W2展馆正对面。这也可…

Electron、Win11静默打印与PowerShell:技术融合与应用探索

Electron、Win11静默打印与PowerShell&#xff1a;技术融合与应用探索 在现代软件开发与办公环境中&#xff0c;技术的融合与创新不断推动着工作效率的提升和用户体验的优化。本文将深入探讨Electron框架、Windows 11&#xff08;Win11&#xff09;静默打印技术以及PowerShell…

Win11禁止右键菜单折叠的方法

背景 在使用windows11的时候&#xff0c;会发现默认情况下&#xff0c;右键菜单折叠了。以至于在使用一些软件的右键菜单时总是要点击“显示更多选项”菜单展开所有菜单&#xff0c;然后再点击。而且每次在显示菜单时先是全部展示&#xff0c;再隐藏一下&#xff0c;看着着实难…

小试牛刀-区块链代币锁仓(Web页面)

Welcome to Code Blocks blog 本篇文章主要介绍了 [区跨链代币锁仓(Web页面)] ❤博主广交技术好友&#xff0c;喜欢我的文章的可以关注一下❤ 目录 1.编写目的 2.开发环境 3.实现功能 4.代码实现 4.1 必要文件 4.1.1 ABI Json文件(LockerContractABI.json) 4.2 代码详解…

《新华日报》理论版报刊简介及投稿邮箱

《新华日报》理论版报刊简介及投稿邮箱 《新华日报》是中国共产党在抗日战争时期和解放战争初期创办的大型机关报&#xff0c;1949 年 4 月在南京复刊&#xff0c;1952 年成为中国共产党江苏省委机关报&#xff0c;现为中共江苏省委直属事业单位。 该报纸的理论版&#xff08;…

pycharm无法添加python解释器的解决方法

出现该错误的原因是先前创建过重名的解释器&#xff08;虚拟环境&#xff09;&#xff0c;在pycharm配置中没有完全删除干净。解决方法如下&#xff1a; 首先在文件->设置界面&#xff0c;找到解释器设置。 然后先按图所示点击全部显示虚拟环境&#xff1a; 接着将无法添…

Django开发实战(1)- 认识django

1.django 使用MTV模式&#xff0c;其实与MVC本质一样&#xff1a; model&#xff1a;业务对象和关系映射&#xff08;ORM&#xff09; template&#xff1a;客户端页面展示 view&#xff1a;业务逻辑&#xff0c;根据需求调用 2.开发相关 √ python √ html&…

高压开关触指接触压力测试仪 隔离开关触指压紧力测试仪

产品概述 KDGK-2016隔离开关触指压紧力测试仪&#xff0c;只要将测试钳模拟触头的传感器在每对触指接触位置张开一下&#xff0c;就能显示出触指此时的接触压力并记忆。有效解决了测量触指压力的难题。 KDGK-2016隔离开关触指压紧力测试仪也可用于隔离开关制造厂对触指压力的…

工作坊回顾 | 谢宁老师赋能一汽汽车集团开展《从市场洞察到产品规划及产品线端到端经营管理》专题工作坊

工作坊现场快报 近日&#xff0c;《华为战略管理法&#xff1a;DSTE实战体系》作者、著名战略管理专家谢宁老师赋能一汽汽车集团&#xff0c;开展《从市场洞察到产品规划及产品线端到端经营管理》工作坊。 一汽汽车集团相关产品线团队成员&#xff08;涉及到研发、生产、市场、…

备忘:PythonREPL中py_repl.run方法执行报错和修改方法

PythonREPL是python提供的 “Read–Eval–Print Loop”&#xff08;读取-求值-打印-循环&#xff09;的缩写&#xff0c;它是一种简单的、交互式的编程环境&#xff0c;我们之前在用AI生成代码后执行就使用这个方法&#xff0c;例如 def py_repl_tool(self, realcode: str):py…