当前位置: 首页 > ds >正文

【C++11】折叠引用和完美转发

目录

  • 一. 前言
  • 二. 引用折叠
    • 引用折叠的规则
  • 三. 完美转发
    • 完美转发适用场景
    • 完美转发底层实现
      • 思考1
      • 思考2

一. 前言

在函数传参时,如果想保持某个参数的属性不改变,需要完美转发,而完美转发的实现需要折叠引用的帮助

二. 引用折叠

在语法上,c++不能定义引用的引用,如 int & && r=i,这样会报错,但是通过模板或typedef的类型可以构成引用的引用,

引用折叠的规则

  1. 除了右值引用的右值引用,其他组和都是左值
  • T& & → T& (左值引用的左值引用折叠为左值引用)

  • T& && → T& (左值引用的右值引用折叠为左值引用)

  • T&& & → T& (右值引用的左值引用折叠为左值引用)

  • T&& && → T&& (右值引用的右值引用折叠为右值引用)

  1. 通过引用规则我们发现,T&&的结果可以保持T本身的属性,所以T&&也被称为万能引用,

三. 完美转发

完美转发适用场景

从下图可以看出,在最开始Function函数中传入的是右值,但在Func中却变成了左值,这是由于右值表达式的属性是左值,
在这里插入图片描述

这样就破坏了最开始传入的值的属性
想要保持表达式的属性,就需要用完美转发来解决,见下图
在这里插入图片描述

完美转发底层实现

完美转发的本质是函数模板,通过引用折叠实现,在forward内部进行强转,然后再引用折叠返回,
std::remove_reference_t& t 移除T最外层的引用修饰,使不管传入什么类型,t的类型都是左值引用类型

思考1

思考1:为什么需要保证t的类型是左值引用?
直接用原类型不行么 T&& forward(T&& t)
传入左值时,T被推导为T&,T&->T&,没有问题
传入右值时,T被推导为T,T->T&&,左值向右值转化,危险操作

template <class T>
T&& forward(std::remove_reference_t<T>& t)
{//std::remove_reference_t<T> 类型萃取模板,移除T的最外层引用修饰,return static_cast<T&&>(t);·
}
template <class T>
void Function(T&& t)
{//Func(std::forward<T>(t));Func(forward<T>(t));//Func(t);
}int main()
{int&& n = 10;Function(n);return 0;
}

思考2

思考2:为什么需要用std::remove_reference_t& 来移除最外层修饰的引用,
T&& forward(T& t) 不行么?
传入左值时
T& && forward(T& & ) 实例化-> T& forward(T & ) 没有问题
传入右值时
T&& && forward(T&& & ) 实例化-> T&& forward(T & ) 看似没有问题
虽然 int&& & 理论上可以折叠为 int&,但 C++ 类型系统禁止直接声明这种组合:

http://www.xdnf.cn/news/11046.html

相关文章:

  • Leetcode 1336. 每次访问的交易次数
  • 【C/C++】公共接口调用:aaa.so: undefined reference to `GetXXX‘
  • 实现购物车微信小程序
  • Seata的AT、TCC、Saga模式的区别及适用场景?
  • 如何轻松删除 Android 上的文件(3 种方法)
  • lanqiaoOJ 1508:N皇后问题 ← dfs
  • Linux进程间通信(IPC)
  • TypeScript 中的字面量类型(Literal Types)
  • 什么是 Docker Compose 的网络(network),为什么你需要它,它是怎么工作的
  • 词语翻译的三步法与背后的语言学思维
  • R²AIN SUITE AI知识库助力中国制造业数字化转型
  • ABAP设计模式之---“高内聚,低耦合(High Cohesion Low Coupling)”
  • 嵌入式学习 D31:系统编程--Framebuf帧缓冲
  • java实用类
  • 【Agent智能体】吴恩达:AI智能体发展现状 | LangChain访谈--快速总结
  • 电脑远程桌面连接如何设置端口?默认修改和内网给外网访问方法
  • ArkUI-X中Plugin生命周期开发指南
  • 不连网也能跑大模型?
  • 手机上网可以固定ip地址吗?详细解析
  • Ubuntu22.04 安装 Miniconda3
  • python直方图
  • 【前端并发请求控制:必要性与实现策略】
  • 为何选择Spring框架学习设计模式与编码技巧?
  • 从“remote rejected”看git角色区别,Maintainer和Devoloper
  • 使用 Docker Compose 安装 Redis 7.2.4
  • Python基于PCA、PCA-kernel、LDA的同心圆数据降维项目实战
  • 2005-2022全国及各省家庭承包耕地流转总面积及经营耕地面积数据(无缺失)
  • 移动网页调试的多元路径:WebDebugX 与其他调试工具的组合使用策略
  • HarmonyOS Next 弹窗系列教程(2)
  • matlab实现掺杂光纤放大器的模拟