C++11:右值引用,实现移动语义和完美转发

目录

1、右值引用

2、移动语义(std::move)

3、完美转发(std::forward)


1、右值引用

右值引用(Rvalue reference)是C++11引入的一个新特性,它是一种新的引用类型,用于表示将要被移动的对象或临时对象。

(1)首先了解几个关键名词:

(1)左值:可以取地址的表达式,并且有名字;

(2)右值:不能取地址的表达式,且没有名字;

(3)纯右值:运算表达式产生的临时变量,不和对象关联的原始字面量、非引用返回的临时变量、lambda表达式都是纯右值;

(4)将忘值:即将销毁的值;

(5)左值引用&:对左值进行引用的类型,等号右边的值必须可以取地址

(6)右值引用&&:对右值进行引用的类型,等号右边的值需要是右值,可以使用std::move函数强制把左值转换为右值。

(2)相关的代码展示:

int a = 1;  // a是左值
int b = a;  // a是左值,b是左值
int c = a + b;  // a和b是右值,c是左值
int&& rvalue_ref = 1;  // rvalue_ref是右值引用

int &&d = a; // error, a是左值
int &&e = std::move(a); // ok

2、移动语义(std::move)

(1)移动语义含义:转移资源所有权,类似转让或者资源窃取,对于那块资源,转为自己所拥有,别人不再拥有也不会再使用;理解深浅拷贝,直接把原来需要拷贝的内存易主

在C++11之前,我们拥有4个特殊成员函数,即构造函数、析构函数、拷贝构造函数以及拷贝赋值运算符。从C++11开始,我们多了2个特殊成员函数,即移动构造函数和移动赋值运算符。

在C++11之后,如果我们定义一个空类,除了之前的4个特殊成员函数,编译器还会为我们生成移动构造函数和移动赋值运算符: 

但是我们自定义一些函数时候,可能就不一定会自动生成移动构造函数和移动赋值运算符,相关的关系看下面的表:

(2)右值引用的主要作用是实现移动语义(Move Semantics),即在对象的拷贝或赋值操作中,将资源的所有权从一个对象转移到另一个对象,避免不必要的拷贝和内存分配。例如:

// 例子1
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2 = std::move(vec1);  // 使用右值引用实现移动


// 例子2
std::vector<string> vecs;
...
std::vector<string> vecm = std::move(vecs); // 免

//类的
int main() 
{
	A a(10);
	A b = a;
	A c = std::move(a); // 调用移动构造函数
	return 0;
}

例子1:在上面的代码中,使用std::move将vec1转换为右值引用,然后将其赋值给vec2。由于vec1已经成为右值,因此可以安全地将其资源(即动态分配的内存)转移给vec2,避免了不必要的拷贝和内存分配。

注意:移动语义仅针对于那些实现了移动构造函数的类的对象,对于那种基本类型int、float等没有任何优化作用,还是会拷贝,因为它们实现没有对应的移动构造函数。

还需要关注的重点在于我们需要把传入对象A的数据清除,不然就会产生多个对象共享同一份数据的问题。被转移数据的对象会处于"有效但未定义(valid but unspecified)"的状态。原本的指针要置空。

(3)避免非必要的std::move调用

在C++中,存在称为"NRVO(named return value optimization,命名返回值优化)"的技术,即如果函数返回一个临时对象,则该对象会直接给函数调用方使用,而不会再创建一个新对象。

当返回局部对象时,我们不用画蛇添足,直接返回对象即可,编译器会优先使用最佳的NRVO,在没有NRVO的情况下,会尝试执行移动构造函数,最后才是开销最大的拷贝构造函数。

3、完美转发(std::forward)

(1)右值引用还可以用于实现完美转发(Perfect Forwarding),即在函数模板中将参数按原样转发给另一个函数。即是:转发函数实参是左值,那目标函数实参也是左值;(右值同理)

(2)使用 std::forward 的示例:

#include <iostream>
#include <utility>

template<typename T>
void print(T&& arg) {
    std::cout << "Printing: " << std::forward<T>(arg) << std::endl;
}

int main() {
    int a = 5;
    const int b = 10;
    print(a); // T is int&, arg is int&
    print(b); // T is const int&, arg is const int&
    print(15); // T is int, arg is int&&
    return 0;
}

在这个示例中,我们定义了一个名为 print 的模板函数,接受一个类型为 T 的参数 arg。在函数体内,我们通过 std::forward 将 arg 转发给 std::cout,保留其原始值类型和常量性质。

在 main 函数中,我们分别调用 print 函数,传递了一个 int 类型的变量 a,一个 const int 类型的变量 b,以及一个 int 字面量 15。当我们传递 a 和 b 时,T 的类型分别为 int& 和 const int&,因此 arg 的类型也分别为 int& 和 const int&。当我们传递 15 时,T 的类型为 int,arg 的类型为 int&&。

在每个调用中,我们使用 std::forward 将 arg 转发给 std::cout,以便正确地保留其原始类型和常量性质。例如,当 T 为 int& 时,std::forward<T>(arg) 将返回 arg 的左值引用,而当 T 为 int&& 时,std::forward<T>(arg) 将返回 arg 的右值引用。

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

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

相关文章

接口测试 —— 接口测试定义

1、接口测试概念 &#xff08;重点&#xff09; 接口测试是测试系统组件间接口的一种测试&#xff0c;它界于单元测试与系统测试中间。 接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。 测试的重点是要检查数据的交换&#xff0c;传递和控制管理过…

浅入浅出 iptables 网络隔离原理

01 iptables简介 iptables ipfirewall&#xff08;内核1.x时代&#xff09; ipchains&#xff08;内核2.x时代&#xff09; iptables 网络协议栈 Link Layer 数据链路层的数据流向&#xff0c;根据mac寻址找到对应的网卡后向上进入网络层 Network Layer 网络层的数据流向&am…

磁盘配额与进阶文件系统管理(一)

磁盘配额Quota 用途 针对www server&#xff0c;例如 每个人网页空间的容量限制&#xff1b;针对mail server&#xff0c;例如 每个人的邮件空间限制&#xff1b;针对file server&#xff0c;例如 每个人最大可用的网络硬盘空间&#xff1b;限制某一群组所能使用的最大磁盘空…

ArrayList源码

介绍 ArrayList非线程安全。ArrayList基于动态数组&#xff0c;是一种线性表。随机访问友好&#xff0c;插入和删除效率低。 ​ 增删慢&#xff1a;每次删除元素&#xff0c;都需要改变数组长度、拷贝以及移动数组长度 ​ 查询快&#xff1a;由于数组在内存中是一块连续空间…

中国计算机学会CCF推荐的国际会议(图像处理方向)

CCF推荐的国际会议&#xff08;医学图像处理方向&#xff09; 1 介绍2 最新目录3 投了会议可以再投期刊吗&#xff1f;4 个人感想 1 介绍 CCF根据论文的质量和影响力&#xff0c;对国际期刊和国际会议进行了评估和分类&#xff0c;以便研究者在选择发表论文或参与学术交流时有…

94.构建样品餐部分第二节

上节课完成的页面是这样的 ● 之后我们设置一下图标 .meal-attribute {font-size: 1.8rem;font-weight: 500;display: flex;align-items: center;gap: 1.6rem; }.meal-img {width: 100%; }.meal-icon {height: 2.4rem;width: 2.4rem;color: #e67e22; }● 为了突出这些参数的…

CDH 之 hive 升级至 hive-3.1.3 完美踩坑过程

一、准备工作 1.1 前言 这是博主在升级过程中遇到的问题记录&#xff0c;大家不一定遇到过&#xff0c;如果不是 CDH 平台的话&#xff0c;单是 hive 服务升级应该是不会有这些问题的&#xff0c;且升级前博主也参考过几篇相关 CDH 升级 hive 服务的博文&#xff0c;前面的升级…

Java实现LL1语法分析器【编译原理】

java通过预测分析法实现语法分析程序【编译原理】 前言推荐实验要求需知LL1工作原理 Java实现LL1语法分析器0实验步骤LL1.javaGrammar.javaLeftRecursion.javaFirstAndFollow.javaAnalyzeTable.javaLL1Stack.java实验结果 Java实现LL1语法分析器1Grammar.javaProduction.javaFi…

Neo4j安装配置教程

目录结构 前言Neoj4简介安装JDKNeo4j安装步骤Neo4j下载解压Neo4j压缩包配置环境变量启动Neo4j执行命令报错&#xff0c;报错信息如下&#xff1a; 启动Neo4j&#xff0c;再次测试浏览器访问Neo4j参考链接 前言 安装所需配件网盘一键下载。以下描述中&#xff0c;官网下载均有描…

5.3图的综合应用算法

一.最小生成树算法 1.概念&#xff08;Minimum-Spanning-Tree&#xff09;MST 生成树&#xff1a;针对于连通图&#xff0c;包含全部顶点&#xff0c;去掉一条边后不连通&#xff0c;加一条边形成环 最小生成树:带权连通无向图&#xff0c;边的权值之和最小的生成树(MST) 2.…

基于LPP算法实现MNIST数据集降维

目录 1、作者介绍2、LPP算法简介2.1 基本概念及原理2.2 算法流程 3、LPP算法实现3.1 数据集简介3.2 代码实现3.2.1 完整代码3.2.2 运行结果 4、参考链接 1、作者介绍 刘晨雨&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2022级研究生 研究方向&#xff1a;…

Tomcat部署

Tomcat 一、Tomcat什么是 servlet&#xff1f;什么是 JSP?Tomcat 功能组件结构&#xff1a;Container 结构分析&#xff1a;Tomcat 请求过程&#xff1a; 二、Tomcat服务部署三、虚拟主机配置四、Tomcat多实例部署 Tomcat 是 Java 语言开发的&#xff0c;Tomcat 服务器是一个免…

前端录制回放rrweb

rrweb 是 ‘record and replay the web’ 的简写&#xff0c;旨在利用现代浏览器所提供的强大 API 录制并回放任意 web 界面中的用户操作。 rrweb中文文档 https://github.com/rrweb-io/rrweb/blob/master/guide.zh_CN.md 本文项目地址 https://github.com/qdfudimo/vue-rrweb…

目标检测算法:YOLO v1论文解读

目标检测算法&#xff1a;YOLO v1论文解读 前言 ​ 其实网上已经有很多很好的解读各种论文的文章了&#xff0c;但是我决定自己也写一写&#xff0c;当然&#xff0c;我的主要目的就是帮助自己梳理、深入理解论文&#xff0c;因为写文章&#xff0c;你必须把你所写的东西表达清…

深入了解Java虚拟机之高效并发

目录 Java内存模型与线程 概述 硬件的效率与一致性 Java内存模型 主内存与工作内存 内存间交互操作 对于volatile型变量的特殊规则 原子性、可见性与有序性 先行发生原则 Java与线程 线程实现 线程调度 状态切换 小结 线程安全与锁优化 概述 线程安全 Java中…

简单的UDP网络程序·续写

该文承接文章 简单的UDP网络程序 对于客户端和服务端的基本源码参考上文&#xff0c;该文对服务器润色一下&#xff0c;并且实现几个基本的业务服务逻辑 目录 demo1 第一个功能&#xff1a;字典翻译 初始化字典 测试代码&#xff1a;打印 字符串分割 客户端修改 成品效果…

AI宝典:AI超强工具大整合

&#x1f604;&#x1f604;个人介绍 光子郎.进行开发工作七年以上&#xff0c;目前涉及全栈领域并进行开发。会经常跟小伙伴分享前沿技术知识&#xff0c;java后台、web前端、移动端&#xff08;Android&#xff0c;uniapp&#xff0c;小程序&#xff09;相关的知识以及经验体…

C#发送邮箱设置及源码

用C#调用发送邮箱代码之前需要邮箱开通SMTP/POP3及设置授权码&#xff0c;开通及获取方法如下&#xff1a; 1、打开邮箱&#xff0c;登录邮箱&#xff0c;进入设置&#xff0d;》帐户 2、在“帐户”设置中&#xff0c;找到服务设置项&#xff0c;进行设置&#xff0c;如下…

[Flink] Flink On Yarn(yarn-session.sh)启动错误

在Flink上启动 yarn-session.sh时出现 The number of requested virtual cores for application master 1 exceeds the maximum number of virtual cores 0 available in the Yarn Cluster.错误。 版本说明&#xff1a; Hadoop&#xff1a; 3.3.4 Flink&#xff1a;1.17.1 问题…

Python实战基础20-解密文件及目录操作

任务1 为泸州驰援湖北的89名白衣勇士点赞 【任务描述】 设计python程序&#xff0c;实现用户可以为泸州驰援湖北的89名白衣勇士点赞留言。用户点赞留言内容保存到本地txt文件中。 import os # 导入os模块 import random # 导入随机模块 import string # 导入string模块# 定义…