C++ 右值引用深入理解:特性、优化与底层

目录

一、左右值的概念及右值的种类

二、左值引用与右值引用

左值引用给右值取别名:

右值引用给左值取别名:

三、引用的意义及左值引用的场景

四、移动构造:

右值引用在底层里的实现:


一、左右值的概念及右值的种类

在 C++ 中,左右值的区分对于理解语言的行为至关重要。一般来说,可以取地址的是左值,不可以取地址的是右值。同时,被 const 修饰的通常也被视为左值。

右值主要包括以下几种类型:

  1. 常量,例如 10,它们在程序运行期间具有固定的值,且通常存储在只读内存区域。
  2. 临时对象,如 string("1111"),这些对象是在表达式中临时创建的,通常在包含它们的完整表达式结束后就可能被销毁。
  3. 匿名对象,例如 string("666"),没有名字的对象,同样也是临时创建的,生命周期较短。
	//右值10;//常量string("1111");//临时对象string("666");//匿名对象

二、左值引用与右值引用

  1. 左值引用给右值取别名

    • 不能直接用左值引用给右值取别名,但是使用 const 左值引用是可以的。这是因为 const 左值引用可以绑定到临时对象,确保在引用期间不会修改这个临时对象。例如 const int& a = 10;,这里 a 是一个常量引用,绑定到了右值 10
  2. 右值引用给左值取别名

    • 不能直接用右值引用给左值取别名,但是可以通过 std::move 将左值转换为右值后,再用右值引用进行引用。例如 int c = 100; int&& b = move(c); 和 int&& d = (int&&)c;
    • std::move 的作用是将左值转换为右值,本质上类似于强制类型转换。在底层实现中,无论是左值引用还是右值引用,实际上都是指针的形式,这也说明了在底层并没有真正的 “引用” 概念,而 move 更多的是在语法层面上进行类型转换。
int c = 100;
const int& a = 10;
int&& b = move(c);
int&& d = (int&&)c;

move:将左值转化为右值,本质等同于强转,所以上面的b与d没区别

move的讲解:move - C++ Reference (cplusplus.com)

三、引用的意义及左值引用的场景

引用在 C++ 中有重要的意义,主要是减少拷贝操作,提高程序的性能。

左值引用主要解决的场景包括引用传参和引用传返回值。通过引用传参,可以避免不必要的对象拷贝,特别是对于大型对象,这种方式可以显著提高程序的效率。在函数返回值时,如果返回左值引用,可以避免返回对象时的拷贝构造,直接返回对象的引用,提高程序性能。

然而,左值引用在某些情况下并没有彻底解决问题。例如,当传值返回的时候,如果返回的是左值,那么只能通过拷贝构造来解决问题。但是当遇到大数据结构(如 std::list 等)的深拷贝时,会非常浪费时间,这时候右值引用的价值就体现出来了。

四、移动构造

对于自定义类,可以定义移动构造函数来处理右值。例如对于 std::string 类,移动构造函数的形式可能是 string(string&& s),在这个函数中,通过 swap(s) 操作,将即将消亡的右值对象的数据交换过来,避免了不必要的拷贝操作。这样做的好处是,获取要消亡的数据,把自身不需要的数据给右值对象 s,让它去销毁,而自身获取有用的数据,不再需要进行拷贝。

string(string&& s)
{swap(s);
}

只有进行深拷贝的类才有移动构造的意义,因为只有在深拷贝的情况下,避免拷贝操作才能带来显著的性能提升。

右值返回种类:

存右值:内置类型右值

将亡值:类类型的右值

移动构造:swap(s),将要消亡的交换,获取要消亡的数据,把‘我’不要的数据给s,让他去销毁,而我获取有用的数据,不需要拷贝了吗

拷贝构造:传值返回时,编译器将要先把返回的数据先生成临时对象在拷贝给所需的对象优化成了直接把返回的数据拷贝给所需对象,将俩次拷贝优化成了一次

深拷贝的类才有移动构造的意义

在string s1 (s2)编译器开的优化大,构造加拷贝/移动构造 = 直接构造。相当于直接引用的main函数的对象—vs2022.不是所以编译器都这样  构造可以这么激进的优化,但是赋值不可以

移动赋值string s1 = (s2)

右值引用在底层里的实现:

R1右值引用的属性本身是---》左值  :因为swap什么的需要修改   

左值和右值可以来回切,本质只是语法层的限制

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Excel重新踩坑3:条件格式;基本公式运算符;公式中的单元格引用方式;公式菜单栏其他有用的功能说明;

0、前言:以下内容是学习excel公式的基础内容。 1、需求:将表格特定区域中数值大小大于等于30,小于等于80的单元格,颜色填充为红色,大于80的,颜色填充为黄色。 新建规则之后也可以通过该功能清除规则。 2、基…

使用InternVL、LMDeploy和GTE搭建多模态RAG系统

如何将视觉大模型(VLM)与 多模态RAG 结合起来,创建服装搜索和搭配推荐!本文展示了InternVL模型在分析服装图像和提取颜色、款式和类型等关键特征方面的强大功能。 InternVL2是国内首个在MMMU(多学科问答)上突破60的模型&#xff0…

一次使用LD_DEBUG定位问题的经历

在实际工作中,当遇到段错误,我们会很容易的想到这是非法访问内存导致的,比如访问了已经释放的内存,访问数据越界,尝试写没有写权限的内存等。使用gdb进行调试,查看出异常的调用栈,往往可以定位到…

告别装机烦恼,IT小白到IT大神都在用的免费神器

作为USB启动盘制作工具中的佼佼者,Rufus凭借其卓越的性能和实用性,赢得了众多用户的信赖。这款精巧的实用程序不仅能够将系统ISO镜像完美转换为可引导的USB安装介质,还提供了全面的USB设备管理功能。 Rufus的安装包仅有1.5M大小,…

ubuntu系统库和Anaconda库冲突问题

之前安装opencv时没出现过这种问题,自从安装Anaconda后就总遇到问题。记录下自己的解决过程。 目录 第一步 第二步 第三步 安装opencv时出现以下问题: /usr/bin/ld: /lib/x86_64-linux-gnu/libwayland-client.so.0: undefined reference to `ffi_prep_cif@LIBFFI_BASE_7.…

qt QTableview 左侧 序号 倒序

本文主要在QTableview插入数据的基础上,使左边序号实现倒序,实现如下图所示。 解决办法: QTableview左侧是QHeaderView类构成的,重写QHeaderView的paintSection, 重写序号的文字内容,进而 实现QTableview …

FFT过程中自动补零,补零部分FFT结果不为零

在 FFT(快速傅里叶变换) 中,补零(Zero Padding)是为了使信号的点数符合 2 的幂次方,以提高 FFT 的计算效率。然而,即使你对信号进行了补零,FFT 计算后在补零部分可能会得到复数结果不…

医院信息化与智能化系统(5)

医院信息化与智能化系统(5) 这里只描述对应过程,和可能遇到的问题及解决办法以及对应的参考链接,并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图,可以试试PlantUML,告诉GPT你的文件结构,让他给你对应的…

python 文件防感染扫描

一、安装 首先,你需要安装 secplugs-python-client 库。你可以通过 pip 命令来安装: pip install secplugs-python-client确保你的 Python 环境已经正确设置,并且网络连接畅通,以便能够顺利安装。 二、基本用法 1. 初始化客户…

nosql课本习题

nosql题目 1. 文档数据库相比其他 NoSQL 的突出优势和特点是什么? 答案: 文档数据库的突出优势在于它的灵活性和可扩展性。不同于传统的关系型数据库,文档数据库允许存储半结构化和非结构化数据,每个文档可以有不同的字段&#x…

【优先算法】--双指针1

“一念既出,万山无阻。”加油陌生人! 目录 1.双指针--移动零 2.双指针-复写零 ok,首先在学习之前,为了方便大家后面的学习,我们这里需要补充一个知识点,我这里所谓的指针,不是之前学习的带有…

二分查找_ x 的平方根搜索插入位置山脉数组的峰顶索引

x 的平方根 在0~X中肯定有数的平方大于X&#xff0c;这是肯定的。我们需要从中找出一个数的平方最接近X且不大于X。0~X递增&#xff0c;它们的平方也是递增的&#xff0c;这样我们就可以用二分查找。 我们找出的数的平方是<或者恰好X&#xff0c;所以把0~X的平方分为<X …

Leetcode—1279. 红绿灯路口【简单】Plus(多线程)

2024每日刷题&#xff08;186&#xff09; Leetcode—1279. 红绿灯路口 C实现代码 class TrafficLight { public:TrafficLight() {}void carArrived(int carId, // ID of the carint roadId, // ID of the road the car travels on. Can …

【Linux】僵尸进程和孤儿进程

一、僵尸进程 何为僵尸进程&#xff1f; 在 Unix/Linux 系统中&#xff0c;正常情况下&#xff0c;子进程是通过父进程创建的&#xff0c;且两者的运行是相互独立的&#xff0c;父进程永远无法预测子进程到底什么时候结束。当一个进程调用 exit 命令结束自己的生命时&#xff…

【Linux】计算机网络协议详解与通信原理探究

目录 1、协议 1.1.初识协议 1.2.协议分层 日常通信的例子&#xff1a; 1.3.OSI 七层模型 1.4.TCP/IP五层(或四层)模型 1.5.OS和网络之间的关系 1.6.协议的本质 2.局域网通信 2.1.什么是局域网&#xff1f; 2.2.关于报文相关基础知识 报文和协议的关系&#xff1a; …

传输层协议UDP详解

目录 一. 知识准备 1.1 传输层 1.2 重识端口号 二. UDP协议 三. UDP协议特点 一. 知识准备 1.1 传输层 前面已经讲过&#xff0c;HTTP协议是应用层协议&#xff0c;在此之前&#xff0c;我们短暂的认为HTTP是直接通过应用层与外界通信的。但是我们要知道&…

4本SCI/SSCI期刊更名,10月WOS更新!速看!

期刊动态 2024年10月科睿唯安期刊目录更新 2024年10月22日&#xff0c;科睿唯安更新了WOS期刊目录&#xff0c;此次更新&#xff0c;期刊被编辑除名11本&#xff0c;停止出版1本&#xff0c;4本更名&#xff0c;停产1本&#xff0c;新增63本。 剔除期刊 11本期刊被剔 Enginee…

go-zero系列-限流(并发控制)及hey压测

参考地址&#xff1a; go-zero系列-限流(并发控制)&#xff1a;https://go-zero.dev/docs/tutorials/service/governance/limiter hey地址&#xff1a;https://github.com/rakyll/hey1、压测工具hey下载安装&#xff1a; 会安装到GOPATH/bin目录下 go install github.com/ra…

AI未来会拥有人类的情感吗,情感计算领域进展如何?

AI在情感理解方面目前还处于相对初级的阶段,但已经有了一些令人鼓舞的进展。 一般来说,AI系统可以通过自然语言处理和计算机视觉技术来检测和分析人类的情感表现,但要真正理解背后的情感原因和动机还面临很大挑战。 目前在情感计算领域&#xff0c;研究者们已经取得了显著的进…

重生之“我打数据结构,真的假的?”--1.顺序表(无习题)

C语言中的顺序表详细总结 1. 概述 顺序表&#xff08;Sequential List&#xff09;是一种线性数据结构&#xff0c;用于存储具有相同数据类型的一组元素。顺序表采用一段连续的存储空间&#xff0c;使用数组来实现&#xff0c;能够高效地支持随机访问操作。在 C 语言中&#…