【C++】左值、右值、语义移动和完美转发

news2024/11/15 21:28:24

右值引入的目的是为了对象移动:
因为在很多情况下,对象拷贝会经常发生,但是很多对象在拷贝后就直接被销毁了。这对性能是一个很大损耗。在重新分配内存的时候,从旧的内存将元素拷贝到新的内存中是不必要的。更好的方法是移动元素。

C++11 扩展了右值的概念,分为了纯右值和将亡值。
纯右值:
非引用返回的临时变量;运算表达式的结果;字面常量(“abs”不是,字符串常量是有地址的)
将亡值:与右值引用相关的表达式
左值:是具名的,且有地址

在旧的C++ 标准中是没有直接移动元素的方法,只有拷贝构造函数。为了实现元素移动,引入了【右值引用】的概念。

右值引用的一个重要性质:只能绑定到一个即将销毁的对象。 因此可以自由的将一个右值引用的资源移动到另一个对象中。

而左值是持久的,分配一个内存中的。右值是暂时的,例如一个运算表达式

左值引用可以绑定右值,但是右值引用不能绑定左值。为了实现对左值的右值引用,可以使用std:: move()将一个左值转换成右值。这样就可以实现对左值的右值引用了。注意:调用move后,就不能对移动后的对象值做出任何假设。可以销毁或者重新赋值。

区分一个左值和右值的便捷方法,就是看能不能对其表达式取地址,如果能,就是左值,不能就是右值。

有了右值引用的概念,就可以设计【移动构造函数】和【移动赋值运算符】

类似于拷贝构造函数的设计,第一个参数是对应类别的一个引用,但是这里是右值引用。同时移动构造函数还必须保证,在资源移动之后,对应的源对象的销毁是无害的。移动构造函数是不分配任何新的内存的。

【复制构造器】接受一个左值,之后还能继续用。【移动构造器】直接偷窃资源,偷窃后的源对象就不能用了。

只有一个类没定义任何自己版本的拷贝控制成员,并且类的每一个非static 成员都是可以移动的,编译器才会为它合成移动构造函数或移动赋值运算符。

移动右值,拷贝左值;如果没有移动构造函数,右值也会被拷贝;

左值和右值的参数类型推导

【左值引用函数参数推导】
当一个函数参数的模板类型参数是一个左值引用,只能传递一个左值。

template <typename T> void f1(T&)
f1(5);// error

但是如果一个函数参数是 const T&,那边就可以传递任何类型的实参,可以绑定一个右值。

【右值引用函数参数推导】
C++有两个例外的绑定规则:

  1. 当将一个左值传递给函数的右值引用参数时,且此右值引用指向的是模板类型参数,编译器就可以推导为实参的左值引用类型。
  2. 如果创造了一个引用的引用,那么这些引用就会形成“折叠”,引用会折叠成一个普通的左值引用类型。

将引用折叠规则和右值引用的特殊规则组合在一起,就可以对一个左值调用带模板类型推导的右值引用。
万能引用:万能引用就是发生了类型推导,如果已经确定了类型,如int && 就是右值引用。如果发生了类型推导,那就是万能引用。
C++ 11 中使用了引用折叠 的推导规则。
在这里插入图片描述

template<class T>
void bar(T && t){} // 这里的t就是万能引用
auto && z = get_val(); //z 也是万能引用;

万能引用为的就是完美转发。完美转发就是保持实参的实际类型,如果实参是左值,那么在调用函数中继续保持着其左值属性。右值同理。

template <typename T> void f3(T&& val){
	T t = val; 
}

如果右值调用 f3 如 字面常量 42, T 就是 int。如果是调用左值 i 那么 T 就是 int&。

理解 std:move

template <typename T>
typename reomve_reference<T>::type&& move(T&& t){
 return static_cast<typename remove_reference<T>::type &&>(t);
}

其中 reomve_reference 的作用是返回一个数据结构,其中关键字 type 中包含了变量的类型信息。

从一个左值static_cast 到一个右值引用是允许的。

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

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

相关文章

论文投稿指南——中文核心期刊推荐(天文、测绘学)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

使用Kalibr问题汇总:ModuleNotFoundError: No module named ‘wx‘

问题1&#xff1a; 报错&#xff1a;/kalibr_ws/src/Kalibr/Schweizer-Messer/sm_python/python/sm/PlotCollection.py", line 4, in import wx ModuleNotFoundError: No module named ‘wx’ 解决&#xff1a; sudo apt-get install python3-wxgtk4.0问题2&#xff1…

MySQL补齐函数LPAD和RPAD之SQLite解决方案

工作中经常需要对数据进行清洗&#xff0c;并对个别字段进行格式化处理&#xff0c;像 字符串左右补齐。MySQL数据库自带有LPAD()、RPAD()&#xff0c;而SQLite数据库没有的相应函数&#xff0c;需要自己转换。 目录 1、MySQL数据库 1.1、MySQL左右补全函数 1.2、实践验证 …

阶段性回顾(5)与一些题目实例(数组合并,有序判断,删除元素,进制问题等)

tips 1. 内存栈区的使用习惯是先使用高地址&#xff0c;再使用低地址。并且你还要清楚&#xff1a;随着数组下标的增大&#xff0c;其元素的地址也是在不断变高&#xff1b;对于一个占多个内存单元的变量进行取地址&#xff0c;取出来的是其所占内存空间最低地址的内存单元的地…

Python内存机制 -- = 赋值操作

Python内存机制 python的万物皆对象可不只是说说而已。 1. 预备知识&#xff1a; id()&#xff1a;可以将id()理解为C语言中的*&#xff0c;其返回当前对象在内存中的地址。 int p id(object) # id函数返回对象object在其生命周期内位于内存中的地址&#xff0c;id函数的参数…

Python数据分析案例18——化学分子数据模型(机器学习分类问题全流程)

1. 引言 1.1设计背景 对分子进行分类&#xff0c;对于筛选特定疾病的候选药物是至关重要的。传统的机器学习算法可以对分子进行分类&#xff0c;但是分子不能直接作为机器学习模型的输入&#xff0c;需要进行大量的实验从分子中得到一系列的分子特性。将分子特征使用数字化进…

47-Jenkins-终止构建并设置构建结果

终止构建并设置构建结果前言获取构建结果终止构建并设置构建状态权限问题解决前言 本篇来学习Jenkins终止构建的方法&#xff0c;使用场景&#xff1a;根据前一个构建状态&#xff0c;判断当前构建是否运行 获取构建结果 上次构建结果&#xff1a;currentBuild.getPreviousB…

【LeetCode题目详解】(五)144.二叉树的前序遍历、94.二叉树的中序遍历、145.二叉树的后序遍历、104.二叉树的最大深度、110.平衡二叉树

目录 一、力扣第144题&#xff1a;二叉树的前序遍历 1.解题思路 2.解题代码 二、力扣第94题&#xff1a;二叉树的中序遍历 三、力扣第145题&#xff1a;二叉树的后序遍历 四、力扣第104题&#xff1a;二叉树的最大深度 1.解题思路 2.解题代码 五、力扣第110题&#xff1…

抖音直播间弹幕rpc学习

目标url 随便找个直播间即可。 https://live.douyin.com/198986091107 接口分析 首先并没有在xhr下找到对应的接口 因为采用了websocket来传输信息。切换到ws即可看到 消息下&#xff0c;可以看到16进制的数据在源源不断地增加。 那么我们只要找到反序列化后的数据&…

在wsl下开发T113的主线linux(4)-编译kernel

接下来编译kernel&#xff0c;编译过程可能会出现缺少命令的报错&#xff0c;大概是下面这几个 sudo apt update sudo apt install flex bison bc libncurses-dev 目前linux主线的最新版本并没有适配t113的相关外设驱动&#xff0c;虽然能启动并串口打印&#xff0c;但其他的…

在单选按钮上实现双击效果

如果想让你的用户体验更加极致&#xff0c;可以考虑在对话框上的单选按钮上实现双击效果&#xff0c;以此作为”选中 确定”&#xff08;或者是选中 下一页&#xff0c;或者是选中 完成等&#xff09;的快捷方式。 看看我们需要怎么做 下面是一个对话框模板以及它对应的对…

3.服务注册和远程调用-Nacos[作为注册中心]

1.SpringCloud Alibaba-Nacos[作为注册中心] Nacos 是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理 平台。他是使用 java 编写。需要依赖 java 环境 Nacos 文档地址: https://nacos.io/zh-cn/docs/quick-start.html 下载 nacos-server https://…

HCIA作业整理(2022.12.29)

一、特殊的ip地址&#xff1a; 1.环回地址&#xff1a;127.0.0.1-127.255.255.254 2.受限广播地址&#xff1a;255.255.255.255 3.直接广播地址&#xff1a;主机位全为1、192.168.1.X/24 --- 192.168.1.255 4.网段&#xff1a;主机位全0 --- 192.168.1.X/24 --- 192.168.1…

STL剖析(一):体系结构概览

一.什么是STL? STL全称是Standard Template Library&#xff0c;它属于泛型编程的范畴&#xff08;泛型编程的代表性作品&#xff09;&#xff0c;泛型编程旨在编写独立于数据类型的代码&#xff0c;也就是说代码中的数据类型只有在编译的时候才会确定&#xff0c;否则为一个…

网络协议(一):基本概念、计算机之间的连接方式

网络协议系列文章 网络协议(一)&#xff1a;基本概念、计算机之间的连接方式 目录一、网络互联模型二、计算机之间的通信基础1、计算机之间的连接方式 - 网线直连2、计算机之间的连接方式 - 同轴电缆(Coaxial)3、计算机之间的连接方式 - 集线器(Hub)4、计算机之间的连接方式 -…

vue3 antd项目实战——Form表单的重置与重置【resetFields重置表单未生效(手写重置函数)】

vue3 antd项目实战——resetFields重置表单无效【手写重置函数重置表单数据】关于form表单的文章合集场景复现原因分析解决方案(手写清空函数)关于form表单的文章合集 文章内容文章链接Form表单提交和校验https://blog.csdn.net/XSL_HR/article/details/128495087?spm1001.20…

Hadoop高手之路5-MapRreduce

文章目录Hadoop高手之路5-MapReduce分布式计算框架一、MapReduce概述1.MapReduce核心思想2.MapReduce编程模型3.MapReduce编程实例——词频统计二、MapReduce的工作原理1. MapReduc的工作过程1) 分片、格式化数据源2) 执行MapTask3) 执行Shuffle4) 执行ReduceTask5) 写入文件2.…

5_虚拟机栈

虚拟机栈概述 由于跨平台性的设计&#xff0c;Java的指令都是根据栈来设计的。不同平台CPU架构不同&#xff0c;所以不能设计为基于寄存器的。 优点是跨平台&#xff0c;指令集小&#xff0c;编译器容易实现&#xff0c;缺点是性能下降&#xff0c;实现同样的功能需要更多的指…

QML教程(一)

目录 一、导入 二、对象声明 三、对象属性 1.声明对象属性 2.信号属性 3.方法属性 4.附加属性略 5.枚举属性 6.对象属性赋值 四、自定义对象 一、导入 模块导入 语法&#xff1a; import <ModuleIdentifier> [<Version.Number>] [as <Qualifier>…

【文献阅读】能源受限的无人机和移动充电站进行持续监控的稳健规划

标题&#xff1a;Robust Planning for Persistent Surveillance With Energy-Constrained UAVs and Mobile Charging Stations 作者&#xff1a;Xiaoshan Lin, Yasin Yazıcıo˘glu , and Derya Aksaray 来源&#xff1a;IEEE ROBOTICS AND AUTOMATION LETTERS 摘要 本文考虑…