【深入理解C++】转发、完美转发、std::forward

2023-11-20

前置知识:万能引用、引用折叠

1.转发

#include <iostream>
using namespace std;

template <typename F, typename T, typename Q>
void FuncTemplate(F f, T&& t, Q&& q)    // 函数模板,万能引用
{
	// f是要转发的目标函数
	// 20是右值,T为int类型,t为int&&类型
	// i是左值,Q为int&类型,q为int&类型
	f(t, q);
}

void myfunc(int x, int& y)
{
	x += 10;
	y += 10;
	cout << "x = " << x << ", y = " << y << endl;
	return;
}

int main()
{
	int i = 100;
	FuncTemplate(myfunc, 20, i);
	cout << "i = " << i << endl;

	return 0;
}

在这里插入图片描述

上面代码中的函数模板可以实现 myfunc(int x, int& y) 的转发,但是不能完成 myfunc(int&& x, int& y) 的转发,这是因为 t 虽然是 int&& 类型,但 t 本身是个左值,不能被右值引用 x 接收。

#include <iostream>
using namespace std;

template <typename F, typename T, typename Q>
void FuncTemplate(F f, T&& t, Q&& q)    // 函数模板,万能引用
{
	// f是要转发的目标函数
	// 20是右值,T为int类型,t为int&&类型,但t本身是个左值,不能被右值引用x接收
	// i是左值,Q为int&类型,q为int&类型
	f(t, q);
}

void myfunc(int&& x, int& y)
{
	x += 10;
	y += 10;
	cout << "x = " << x << ", y = " << y << endl;
	return;
}

int main()
{
	int i = 100;
	FuncTemplate(myfunc, 20, i);
	cout << "i = " << i << endl;

	return 0;
}

在这里插入图片描述

2.完美转发

在上面代码中,经历了函数模版参数 t 这一次转发,右值的属性被改变为了左值,为了解决上述问题,这时就需要完美转发了。

#include <iostream>
using namespace std;

template <typename F, typename T, typename Q>
void FuncTemplate(F f, T&& t, Q&& q)    // 函数模板,万能引用
{
	// f是要转发的目标函数
	// 20是右值,T为int类型,t为int&&类型,但t本身是个左值,不能被右值引用x接收
	// i是左值,Q为int&类型,q为int&类型

	f(std::forward<T>(t), q); // forward实现完美转发
}

void myfunc(int&& x, int& y)
{
	x += 10;
	y += 10;
	cout << "x = " << x << ", y = " << y << endl;
	return;
}

int main()
{
	int i = 100;
	FuncTemplate(myfunc, 20, i);
	cout << "i = " << i << endl;

	return 0;
}

在这里插入图片描述

3.std::forward和std::move的区别

#include <iostream>
using namespace std;

void print(int& t) // 形参的类型是左值引用
{
	cout << "print(int& t)" << endl;
}

void print(int&& t) // 形参的类型是右值引用
{
	cout << "print(int&& t)" << endl;
}

template <typename T>
void FuncTemplate(T&& t)    // 函数模板,万能引用
{
	// 20是右值,T为int类型,t为int&&类型,但t本身是个左值,不能被右值引用接收
	print(t);
	print(std::forward<T>(t));
	print(std::move(t));
}

int main()
{
	FuncTemplate(20);

	return 0;
}

输出结果如下:

在这里插入图片描述

#include <iostream>
using namespace std;

void print(int& t) // 形参的类型是左值引用
{
	cout << "print(int& t)" << endl;
}

void print(int&& t) // 形参的类型是右值引用
{
	cout << "print(int&& t)" << endl;
}

template <typename T>
void FuncTemplate(T&& t)    // 函数模板,万能引用
{
	// i是左值,T为int&类型,t为int&类型
	print(t);
	print(std::forward<T>(t));
	print(std::move(t));
}

int main()
{
	int i = 100;
	FuncTemplate(i);

	return 0;
}

输出结果如下:

在这里插入图片描述

4.参考资料

https://www.cnblogs.com/refantasy/p/10026080.html

https://cloud.tencent.com/developer/article/1561681

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【深入理解C++】转发、完美转发、std::forward 的相关文章

随机推荐

  • openssl-1.0.2o.tar.gz 使用

    已经整好的头文件和库下载资源 https download csdn net download ljt350740378 10967124 谢谢 https blog csdn net u010725842 article details
  • saltstack架构拓展syndic

    架构 server1 master 写好httpd nginx 等salt server2 3 minion server4 top master server1 salt key d server4 server4 vim etc sal
  • 【数据库MySQL】-- 视图的作用和使用

    首先介绍一下什么是视图 视图 view 是一种虚拟存在的表 视图中的数据并不在数据库中实际存在 行和列数据来自定义视图的查询中使用的表 并且是在使用视图时动态生成的 通俗的讲 视图只保存了查询的SQL逻辑 不保存查询结果 所以我们在创建视图
  • 北森,SaaS风口上的「新范式」

    在单纯的战略表象背后 成立19年 北森在每一个节点做选择的核心驱动力是什么 这家公司是否拥有自己内部的 组织密码 作者 皮爷 出品 产业家 2013年 纪伟国决定要去美国 取取经 和他同行的还有参与了北森A轮融资的经纬等机构投资人 对于北森
  • IDEA关联MySQL数据库时报错 “Server returns invalid timezone. Go to ‘Advanced‘ tab and set ‘server......”

    具体报错 Server returns invalid timezone Go to Advanced tab and set serverTimezone property manually 解决办法参考 https blog csdn
  • 简单又漂亮:小白入门网页制作

    网页大家平时见的非常多 有的网页简约 有的网页很华丽 那么今天我就来分享一下制作网页的基本操作 就以下面这个网页为例 1 制作网页需要用到的工具 写网页不需要很多工具 因为写出来的网页只是一张图片 没有添加与后台的交互 所以只需要使用HTM
  • vue中使用Echarts地理地图并结合高德地图实现一个国、省、市、区的地图下钻功能

    vue中使用Echarts地理地图并结合高德地图实现一个国 省 市 区的地图下钻功能 一 需求 按不同的层级展示不同的内容 1 中国地图 2 省级地图 3 市级地图 4 县和区以下的地图 二 开发 1 Echarts和地图容器的设置 相关代
  • 优化网站DNS域名解析 进一步提升访问速度

    提高网页的打开速度 一般地我们会选择使用CDN 利用 就近原则 让用户在最短的时间内获取到服务器资源 实际应用当中采用CDN的方式提高网站访问速度的效果也是最明显的 这也就是为什么国外的空间打开速度远不及国内的主机的访问速度的原因了 我们知
  • 1、二层交换机VLAN的划分

    目录 1 手动配置主机IP地址 2 创建vlan 在交换机的全局配置模式下进行 3 分配vlan端口 1 逐一添加 2 分组添加 4 查看vlan配置 1 手动配置主机IP地址 PC PT IP SM PC0 192 168 0 11 25
  • Ubuntu20.04部署android版mediapipe踩坑记录(持续更新。。。)

    1 Android SDK 以及NDK版本问题 根据mediapipe官方文档 SDK要求在28 0 3版本及以上 NDK版本要求介于18和21之间 若版本超出范围容易引发未知的问题 导致无效加班到怀疑人生 注意 SDK build too
  • 机器学习最经典算法-SVM支持向量机-【基本解读算法+详细实际案例分部流程】

    支持向量机 SVM SVM算法可谓是最经典的机器学习算法了 具有泛化错误率低 分类速度快 结果易解释等特点多多 在应用领域涉及非常广 比如人像识别 文本分类 手写字符识别 人脸识别 生物信息学等等等 同时算法模型评估效果也是很优秀的 它为何
  • React 单元测试策略及落地

    写好的单元测试 对开发速度 项目维护有莫大的帮助 前端的测试工具一直推陈出新 而测试的核心 原则却少有变化 与产品代码一并交付可靠的测试代码 是每个专业开发者应该不断靠近的一个理想之地 本文就围绕测试讲讲 为什么我们要做测试 什么是好的测试
  • 自然语言处理nltk下载以及nltk_data下载及其所遇问题解决方案

    目录 一 nltk的下载 二 nltk data 下载 三 解压 nltk data 存放目录可能会出现的问题 一 nltk的下载 新建虚拟环境 conda activate n NLP python 3 8 创建虚拟环境方便管理 激活虚拟
  • IC Compiler指南——数据准备

    一 概述 ICC数据设置的文件关系框图如图 后端工具在数据设置阶段需要对两大类数据进行设置 包括从前端设计继承的综合数据 以及后端设计需要的物理数据 综合数据主要包括前端逻辑综合已经设置过的逻辑与时序库文件 设计约束文件sdc以 及综合网表
  • FileZilla尝试连接“ECONNREFUSED - 连接被服务器拒绝”失败。

    考虑是否在ubuntu下开启了FTP服务 执行以下命令开启 sudo apt get install vsftpd 不能远程登陆 mobaxterm等 unbutu 考虑是否开启了SSH 使用以下命令开启 sudo apt get inst
  • 互联网创业项目整合:提高成功率的关键方法

    互联网创业是当前非常火热的话题 但是市场竞争也异常激烈 成功率不高 今天 我来分享一些互联网创业项目整合的方法 帮助大家创造更大的机会 1 选择适合自己的领域 在选择创业项目时 一定要根据自己的专业 兴趣 经验等因素进行选择 才能更好地发挥
  • clion file and code templates

    主要用于 文件命名为 my class 时 生成的类为 MyClass c class header 和 都是被分割的对象 parse C File Header h ifndef INCLUDE GUARD define INCLUDE
  • L1-039 古风排版(C语言)(测试点2)

    题目 L1 039 古风排版 分数 20 作者 陈越 单位 浙江大学 中国的古人写文字 是从右向左竖向排版的 本题就请你编写程序 把一段文字按古风排版 输入格式 输入在第一行给出一个正整数N lt 100 是每一列的字符数 第二行给出一个长
  • Flickr30k图像标注数据集下载及使用方法

    Flickr30k数据集的下载 可在http shannon cs illinois edu DenotationGraph 中填表 获取下载地址http shannon cs illinois edu DenotationGraph da
  • 【深入理解C++】转发、完美转发、std::forward

    文章目录 1 转发 2 完美转发 3 std forward和std move的区别 4 参考资料 前置知识 万能引用 引用折叠 1 转发 include