右值引用全面剖析

为什么要有右值引用,右值引用出现前程序员们的困境:

在右值引用出现以前,想要把一块内存空间里的内容放到另一块内存空间,只能再开辟一块内存,然后将原来内存里的内容复制到新开辟的内存里,然后再把原来的内存清理掉,这样操作有很大的空间分配和清理的消耗,还容易产生内存碎片

右值引用的出现

右值引用出现使得移动构造和移动赋值得以实现

移动就是指针所有权的转移,原来的 指针1 指向了一块内存,现在再新建一个指针 指针2 指向这块内存,然后让原来的指针1指向空,就完成了一次资源转移,从而实现了右值引用的 终极目标减少复制,提升性能

移动构造没有内存复制,取而代之的是简单的指针替换,没有新内存的申请和旧内存的释放

CharBuffer::CharBuffer(CharBuffer&& temp):size(temp.size),buf(temp.buf)
{cout << "移动构造函数" << endl;temp.buf = nullptr;temp.size = 0;
}

不就是指针转移嘛,反正都是代码实现,为什么拷贝构造里不能进行一样的操作来实现移动语义呢?
因为拷贝构造函数的传参是const无法把原指针指向空,于是会出现两个对象指向同一片内存空间的局面,这时候就容易造成一片空间两次析构的危险

CharBuffer::CharBuffer(const CharBuffer& temp) :size(temp.size), buf(new char[size])
{cout << "拷贝构造函数" << endl;memcpy(buf, temp.buf, size);
}

如果没有自己定义的移动构造函数,通过右值传参其实也是调用的拷贝构造,因为拷贝构造函数的参数是 const 加上const以后,传参就变成了常量,反正也无法被改变,编译器就会自动做出优化,使右值匹配到拷贝构造函数

{CharBuffer test1;CharBuffer test2(move(test1));
}

在这里插入图片描述

同理,传参是 const的都可以接收右值

此外右值往往都是一些临时变量,比如函数返回值,当一个对象的生命周期即将结束,而我们又希望在后续继续使用这个对象,并且又不想用拷贝,因为会产生复制开销,此时就可以通过右值移动来实现延长临时对象的生命周期(将亡值)

std::move()

通过move源代码可以看到

template <class _Ty>
remove_reference_t<_Ty>&& move(_Ty&& _Arg) {return static_cast<remove_reference_t<_Ty>&&>(_Arg);
}

move其实就是把传进来的变成右值引用返回出去(传左值引用就会通过remove_reference移除掉引用变回原本的类型)

所以通过move给一个对象赋值以后如果在对象里没有特别处理的话,原来的对象其实是可以继续用的
就像下面这段代码,是不会报错的,但是会有提醒test1是已经被移动过的对象

{
//错误示范CharBuffer test1;CharBuffer test2(move(test1));auto test3 = test1;cout << test3.size << endl;
}

所以大家其实都是在遵守move结束后不再使用原来的已经被移动了的对象的君子约定,这样更贴合移动的语义,即原对象已经被移动到新对象里,其实原对象还是可以继续使用的(但不要这样做!)

通过forward和万能引用实现完美转发(主要是通过引用折叠推导出是左值引用还是右值引用)

无论一个函数的实参是左值还是右值,他的形参都是左值,所以右值传进函数以后会变成左值,
就像这个里面,不管传进去的是左值还是右值,在TestFunc1里面形参都会变成左值然后调用到左值引用

void TestFunc2(const string& temp) {cout << "左值引用" << endl;
}
void TestFunc2(string&& temp) {cout << "右值引用" << endl;
}void TestFunc1(string& temp)
{TestFunc2(temp);
}void TestFunc1(string&& temp)
{TestFunc2(temp);
}
int main(int argc, char* argv[])
{TestFunc1(string("Jolly"));cout << "==============" << endl;string test1("Jolly");TestFunc1(test1);getchar();return 0;
}

在这里插入图片描述
此时就需要实现完美转发来解决

void TestFunc1(string& temp)
{TestFunc2(static_cast<const string&>(temp));//方法1显式强制转换TestFunc2(std::forward<const string&>(temp));//方法2 forward万能引用模板实现完美转发
}void TestFunc1(string&& temp)
{TestFunc2(static_cast<string&&>(temp));TestFunc2(std::forward<string&&>(temp));
}

通过forward源代码可以看到forward就是把传入进来的都先去引用变回原来的类型,然后经过万能引用推导出应该返回什么类型的引用

template <class _Ty>_Ty&& forward(remove_reference_t<_Ty>& _Arg) {return static_cast<_Ty&&>(_Arg);
}template <class _Ty>_Ty&& forward(remove_reference_t<_Ty>&& _Arg) {return static_cast<_Ty&&>(_Arg);
}

同时也可以通过万能引用模板TestFun1函数换模板函数

template<class T>;
void TestFunc1(T&& temp)//这是万能引用,不是右值引用哦
{TestFunc2(std::forward<T>(temp);
} 

引用折叠规则

在这里插入图片描述

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

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

相关文章

mac下载Homebrew安装nvm

通过Homebrew安装 - 国内下载地址 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"安装nvm brew install nvm 配置nvm环境变量 export NVM_DIR“$HOME/.nvm” [ -s “/usr/local/opt/nvm/nvm.sh” ] && . “/usr/…

解决chatgpt(mac app登陆)出现报错:获取您的 SSO 信息时出错

由于我们是app登陆的&#xff0c;不能直接修改网站的链接&#xff0c;将 URL 的域名部分从 auth.openai.com 变更为 auth0.openai.com&#xff0c;然后加载新的地址&#xff0c;这时候应该就可以正常登录或注册了。 所以我们使用邮箱先载入auth0的地址&#xff0c;再更改自己的…

C#编写的盘符图标修改器 - 开源研究系列文章

这天在网上遇到一个Windows的盘符图标修改软件&#xff0c;但是它那个是.net framework 2.0的&#xff0c;所以就将其改成4.8.1的了&#xff0c;用于Windows 11等默认不安装2.0库的操作系统里使用。 1、 项目目录&#xff1b; 2、 源码介绍&#xff1b; 它直接进行注册表的修改…

【第二部分--Python之基础】03 容器类型的数据

Python内置的数据类型如序列&#xff08;列表、元组等&#xff09;、集合和字典等可以容纳多项数据&#xff0c;我们称它们为容器类型的数据。 序列 序列&#xff08;sequence&#xff09;是一种可迭代的、元素有序的容器类型的数据。 序列包括列表&#xff08;list&#xff…

HTML5实现好看的二十四节气网页源码

HTML5实现好看的新年春节元旦网站源码 前言一、设计来源1.1 主界面1.2 关于我们界面1.3 春季节气界面1.4 夏季节气界面1.5 秋季节气界面1.6 冬季节气界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载结束语 HTML5实现好看的二十四节气网页源码&#xff0c;春季节气&#xf…

走进深圳华为总部参观研学

在这个科技日新月异的时代&#xff0c;每一次与行业标杆企业领先者对话&#xff0c;都是开眼界的好时机。华研标杆游学高老师组织了一场企业家参访团体考察&#xff0c;带大家去到深圳华为总部研学&#xff0c;亲身感受科技巨头的风采&#xff0c;一起探讨未来的发展。 第一站-…

【unity错误】Unity 6 LTS 打开就报错Assertion failed on expressionxxx?

unity6发布已经有一段时间了&#xff0c;如果目前你已经使用了unity6进行项目开发&#xff0c;可能打开会发现如下报错 Assertion failed on expression: ‘!(o->TestHideFlag(Object::kDontSaveInEditor) && (options & kAllowDontSaveObjectsToBePersistent) …

集线器,交换机,路由器,mac地址和ip地址知识记录总结

一篇很不错的视频简介 基本功能 从使用方面来说&#xff0c;都是为了网络传输的标识&#xff0c;和机器确定访问对象 集线器、交换机和路由器 常听到路由器和集线器&#xff0c;下面是区别&#xff1a; 集线器 集线器&#xff1a;一个简单的物理扩展接口数量的物理硬件。…

【ArcGISPro/GeoScenePro】检查并处理高程数据

数据 https://arcgis.com/sharing/rest/content/items/535efce0e3a04c8790ed7cc7ea96d02d/data 数字高程模型 (DEM) 是一种栅格,可显示地面或地形的高程。 数字表面模型 (DSM) 是另一种高程栅格,可显示表面的高度,例如建筑物或树冠的顶部。 您需要准备 DEM 和 DSM 以供分析…

《计算机组成及汇编语言原理》阅读笔记:p177-p177

《计算机组成及汇编语言原理》学习第 13 天&#xff0c;p177-p177 总结&#xff0c;总计 1 页。 一、技术总结 1.real mode A programming model where the program has access to the entire capability of the machine, bypassing security and memory management. Useful…

珞珈一号夜光遥感数据地理配准,栅格数据地理配准

目录 一、夜光数据下载&#xff1a; 二、夜光遥感数据地理配准 三、计算夜光数据值 四、辐射定标 五、以表格显示分区统计 五、结果验证 夜光数据位置和路网位置不匹配&#xff0c;虽然都是WGS84坐标系&#xff0c;不匹配&#xff01;&#xff01;&#xff01;不要看到就直接…

python学习笔记—12—

1. 布尔类型 (1) 定义 (2) 比较运算符 (3) 代码演示 1. 手动定义 bool_1 True bool_2 False print(f"bool_1的内容是&#xff1a;{bool_1}, 类型是&#xff1a;{type(bool_1)}") print(f"bool_2的内容是&#xff1a;{bool_2}, 类型是&#xff1a;{type(bool…

Redis 使用redisTemplate获取某个规则下的key的全量数据(示例Set结构)

如下是redis中存储的数据结构 我想取key以favorites:结尾的所有数据 Redis 的 SCAN 命令用于迭代数据库中的键&#xff0c;支持通过模式过滤结果。模式规则基于 Redis 的通配符匹配语法&#xff0c;类似于文件名匹配规则&#xff1a; *&#xff1a;匹配零个或多个字符。?&…

CertiK《Hack3d:2024年度安全报告》(附报告全文链接)

CertiK《Hack3d&#xff1a;2024年度安全报告》现已发布&#xff0c;本次报告深入分析了2024年Web3.0领域的安全状况。2024年损失总额超过23亿美元&#xff0c;同比增幅高达31.61%&#xff1b;其中&#xff0c;12月的损失金额最少。过去一年&#xff0c;网络钓鱼攻击和私钥泄露…

AI知识库与用户行为分析:优化用户体验的深度洞察

在当今数字化时代&#xff0c;用户体验&#xff08;UX&#xff09;已成为衡量产品成功与否的关键指标之一。AI知识库作为智能客服系统的重要组成部分&#xff0c;不仅为用户提供快速、准确的信息检索服务&#xff0c;还通过用户行为分析&#xff0c;为产品优化提供了深度洞察。…

Vue3 + ElementPlus动态合并数据相同的单元格(超级详细版)

最近的新项目有个需求需要合并单元列表。ElementPlus 的 Table 提供了合并行或列的方法&#xff0c;可以参考一下https://element-plus.org/zh-CN/component/table.html 但项目中&#xff0c;后台数据返回格式和指定合并是动态且没有规律的&#xff0c;Element 的示例过于简单&…

CSS进阶和SASS

目录 一、CSS进阶 1.1、CSS变量 1.2、CSS属性值的计算过程 1.3、做杯咖啡 1.4、下划线动画 1.5、CSS中的混合模式(Blending) 二、SASS 2.1、Sass的颜色函数 2.2、Sass的扩展(extend)和占位符(%)、混合(Mixin) 2.3、Sass的数学函数 2.4、Sass的模块化开发 2.5、Sass…

概率论与数理统计

概率论占比更多&#xff0c;三分之二左右 数理统计会少一些 事件之间的概率 ab互斥&#xff0c;不是ab独立 古典概型吃高中基础&#xff0c;考的不会很多 条件概率公式&#xff0c;要记 公式不要全记&#xff0c;很多有名称的公式是通过基础公式转换而来的 目的在于解决一…

javaEE-多线程进阶-JUC的常见类

juc:指的是java.util.concurrent包&#xff0c;该包中加载了一些有关的多线程有关的类。 目录 一、Callable接口 FutureTask类 参考代码&#xff1a; 二、ReentrantLock 可重入锁 ReentrantLock和synchronized的区别&#xff1a; 1.ReentantLock还有一个方法&#xff1a…

智慧工地系统:建筑施工智能化管理的全新模式

智慧工地概述 智慧工地是将互联网的理念和和物联网的技术引入建筑工地&#xff0c;依托物联网、互联网、大数据、5G技术&#xff0c;建立云端数据平台&#xff0c;形成大数据的业务体系&#xff0c;打通一线操作与远程监管的链条&#xff0c;实现劳务、安全、环境、材料等各个…