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

目录

概念:

理解:

 左值引用,右值引用

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

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

引用的意义是什么?

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

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的操作一样!类似于交换!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

统计信号处理基础 习题解答11-13

题目 如果是一个2x1的随机矢量&#xff0c;具有PDF 证明的PDF是一个随机变量。提可以因式分解成&#xff0c;其中是一个在4.5节描述的白化变换。 解答 首先&#xff1a; 因此&#xff0c;存在&#xff1a; 也就是是Hermitian矩阵。详细的性质可以参考&#xff1a; https://z…

Git使用[推送大于100M的文件后解救办法]

推送大于100M的文件后解救办法 本文摘录于&#xff1a;https://blog.csdn.net/u012150602/article/details/122687435只是做学习备份之用&#xff0c;绝无抄袭之意&#xff0c;有疑惑请联系本人&#xff01; 当有文件大于100M的时候在提交的时候没有问题,但是在push的似乎就不行…

电影院售票管理系统(小白)大佬求解

最近在写一个关于电影院售票管理系统的sm项目&#xff0c;但是在买票的环节出现了问题及点击选座购票&#xff0c;没有数据渲染出来&#xff0c;我不知道什么情况&#xff0c;所以问问。有没有大佬可以帮我解决这个问题&#xff1f;下面是我的。控制层&#xff0c;服务层&#…

学校考场电子钟除了报时,还能做什么?-讯鹏时钟

在学校考场中&#xff0c;电子钟的存在似乎已经司空见惯&#xff0c;大多数人仅仅将其视为报时的工具。然而&#xff0c;学校考场电子钟的作用远不止于此&#xff0c;它具备众多优势和丰富的功能。 学校考场电子钟能够提供精准的时间参考&#xff0c;这是其最基础也是最关键的功…

Qt:5.QWidget属性介绍(Enabled属性-控件可用性设置、geometry属性-控件位置/大小设置)

目录 一、 QWidget属性的介绍&#xff1a; 二、Enabled属性-控件可用性设置&#xff1a; 2.1Enabled属性的介绍&#xff1a; 2.2获取控件当前可用状态的api——isEnabled()&#xff1a; 2.3设置控件当前的可用状态的api—— setEnabled() &#xff1a; 2.4 实例&#xff…

第二十一章 网络编程

​ 一、网络的相关概念 1. 网络通信 &#xff08;1&#xff09;网络通信&#xff1a;将 数据 通过网络从一台设备传输到另一台设备 &#xff08;2&#xff09;java.net 包下提供了一系列的类或接口&#xff0c;完成网络通信 2. 网络 概念&#xff1a;两台或多台设备通过一定…

VideoLLaMA 2:多模态视频理解新突破,音频理解能力再升级,挑战 GPT-4V

前言 近年来&#xff0c;人工智能技术飞速发展&#xff0c;尤其是大模型的出现&#xff0c;为视频理解和生成领域带来了前所未有的机遇。然而&#xff0c;现有的视频大模型&#xff08;Video-LLM&#xff09;在处理视频中复杂的时空信息和音频信息方面仍存在不足&#xff0c;例…

基于矩阵分解算法的评分预测实现---信息检索课设以及所涉及的深度学习原理

一、实验环境 Windows,Python 3 Python作为主要编程语言,使用Python的Pandas、NumPy、Matplotlib等库 二、实验内容 主要任务 查阅相关资料,了解矩阵分解算法的基本概念、应用场景及其难点。重点了解SVD(Singular Value Decomposition,奇异值分解)系列方法。掌握Pyth…

Python特征工程 — 1.4 特征归一化方法详解

目录 1 Min-Max归一化 方法1&#xff1a;自定义的Min-Max归一化封装函数 方法2&#xff1a; scikit-learn库中的MinMaxScaler 2 Z-score归一化 方法1&#xff1a;自定义的Z-score归一化封装函数 方法2&#xff1a; scikit-learn库中的StandardScaler 3 最大值归一化 4 L…

嵌入式c语言3——自定义数据类型

结构体struct&#xff0c;共用体union 结构体中定义变量&#xff0c;首尾地址相连 对于union&#xff0c;其包含变量对起始地址相同 由于其起始地址相同&#xff0c;则改变其中某一变量值时有可能使得另一个变量值发生改变 enum 枚举&#xff0c;可以用来定义一堆整形常量构成…

AzureDataFactory Dataverse connector自动处理了分页问题(单次查询上限5000条的限制)

众所周知&#xff0c;在用fetch执行D365的查询时&#xff0c;单次的查询是5000条&#xff0c;如果超过5000条则需要自己处理分页&#xff0c;添加额外的处理逻辑&#xff0c;但在ADF中&#xff0c;Dataverse connector已经自动处理了分页&#xff0c;我们可以很简单的做个POC. …

昇思25天学习打卡营第05天 | 数据变换 Transforms

昇思25天学习打卡营第05天 | 数据变换 Transforms 文章目录 昇思25天学习打卡营第05天 | 数据变换 TransformsCommon TransformsCompose Vision TransformsText TransformPythonTokenizerLookup Lambda Transforms数据处理模式Pipeline模式Eager模式 总结打卡 通常情况下的原始…

巴图制自动化Profinet协议转Modbus协议模块连接PLC和电表通信

1、免编写Modbus轮询程序实现PLC与电表通信的方法 在智能化时代&#xff0c;工业自动控制中的PLC和电表之间的通信是一个常见的需求。传统上&#xff0c;为了使PLC与电表通信&#xff0c;通常需要编写Modbus查询程序来读取和控制数据。然而&#xff0c;使用 巴图制自动化Prof…

(十二)纹理和采样

纹理 在绘制三角形的过程中&#xff0c;将图片贴到三角形上进行显示的过程&#xff0c;就是纹理贴图的过程 uv坐标 如果如果图片尺寸和实际贴图尺寸不一致&#xff0c;就会导致像素不够用了的问题 纹理与采样 纹理对象(Texture)&#xff1a;在GPU端&#xff0c;用来以一…

安全隔离上网的有效途径:沙箱

在数字化浪潮日益汹涌的今天&#xff0c;网络安全成为了不可忽视的重要议题。沙箱技术作为一种高效的隔离机制&#xff0c;为企业和个人提供了一种在享受网络便利的同时&#xff0c;保障系统安全的解决方案。本文旨在深入探讨沙箱技术如何做到隔离上网&#xff0c;从而为用户提…

(五十二)第 8 章 动态存储管理(边界标识法)

1. 背景说明 2. 示例代码 1) errorRecord.h // 记录错误宏定义头文件#ifndef ERROR_RECORD_H #define ERROR_RECORD_H#include <stdio.h> #include <string.h> #include <stdint.h>// 从文件路径中提取文件名 #define FILE_NAME(X) strrchr(X, \\) ? strr…

QT创建地理信息shp文件编辑器shp_editor

空闲之余创建一个简单的矢量shp文件编辑器&#xff0c;加深对shp文件的理解。 一、启动程序 二、打开shp文件 三、显示shp文件的几何图形 四、双击右边表格中的feature&#xff0c;主窗体显示选中feature的各个节点。 五、鼠标在主窗体中选中feature的节点&#xff0c;按鼠标左…

js学习--制作选项卡

选项卡制作 <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><style>.text_one {width: 11.4%;height: 200px…

web前端开发(概述篇)

一、概念 Web是Internet上的一种多媒体信息服务系统&#xff0c;整个系统由Web服务器、浏览器和通信协议组成。 通信协议HTTP能够传输任意类型的数据对象&#xff0c;满足Web服务器与客户之间的多媒体通信的需求。 一般来说&#xff0c;Web开发分为前端&#xff08;Front-en…

番外篇 | 手把手教你如何去更换YOLOv5的检测头为ASFF_Detect

前言:Hello大家好,我是小哥谈。自适应空间特征融合(ASFF)的主要原理旨在解决单次检测器中不同尺度特征的不一致性问题。具体来说,ASFF通过动态调整来自不同尺度特征金字塔层的特征贡献,确保每个检测对象的特征表示是一致且最优的。本文所做出的改进是将YOLOv5的检测头更换…