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

C++完美转发(适合小白)

        我们知道,C++中有左值引用和右值引用,首先我们要知道什么是左值什么是右值。

        左值:表达式结束后依然存在的持久对象。左值可以出现在赋值语句的左边或右边。例如,变量和函数返回的引用都是左值。左值通常有持久的地址,可以被取地址操作符 & 获取地址。

        右值:通常是临时的,不能有多个引用,它们不指向持久存储。右值可以出现在赋值语句的右边,但不能出现在左边。字面量(如 42 或 "hello")和将亡值(函数返回的非引用类型)都是右值。右值通常用于描述临时对象或字面值,它们在使用后很快就会被销毁。

        那么,在将左值引用和右值引用传入函数的时候,我们有时候需要保存它的左值属性或者右值属性,这时就需要分别写出左值引用和右值引用函数重载。我们也可能需要将不同类型的参数传入函数,这时候就需要用到函数模板。

函数重载如下:

void func(int &n){cout << "左值=" << n << endl;
}void func(int &&m){cout << "右值=" << m << endl;
}

函数模板如下:

//第一种函数模板
template<class T>
void func(T &n){cout << "左值=" << n << endl;
}
template<class T>
void func(T &&m){cout << "右值=" << m << endl;
}//第二种函数模板
void func(int &n){cout << "左值=" << n << endl;
}
void func(int &&m){cout << "右值=" << m << endl;
}
void func(double &n){cout << "左值double=" << n << endl;
}
void func(double &&m){cout << "右值double=" << m << endl;
}template<class T>
void revoke(T &&t){func(t);
}

        第一种能正确输出左右值,但是,它并不能对不同类型的参数调用不同操作(不符合多态),假如你想要int类型的参数打印int,想要double类型的参数打印double,第一种函数无法实现。

        第二种不能正确输出左右值,全部都走到左值,因为t是一个左值变量,只会被转发到左值函数中。

        综上,只有用完美转发才能实现既识别左右值,又能对不同类型的参数调用不同操作。

通过forward<>()实现完美转发

void func(int &n){cout << "左值int=" << n << endl;
}
void func(int &&m){cout << "右值int=" << m << endl;
}
void func(double &n){cout << "左值double=" << n << endl;
}
void func(double &&m){cout << "右值double=" << m << endl;
}template<class T>
void revoke(T &&t){func(forward<T>(t));
}int main(){int i = 10;int &n = i;int &&m = 100;m = 10;//只能识别左右值,不能根据参数类型选择不同操作// func(n);// func(static_cast<int&&>(m));//正确推导revoke(static_cast<int&>(n));revoke(static_cast<int&&>(m));revoke(n);revoke(move(m));    //移动语义,将m的内容移动给一个临时变量,此时传递的是将亡值,会被识别成右值。move之后m的资源被转移,不应该再次使用mdouble d = 1.1;double &dn = d;double &&dm = 10.10;revoke(static_cast<double&>(dn));revoke(static_cast<double&&>(dm));// //err -- 全部是左值// revoke(n);// revoke(m);// //err -- 全部是右值// revoke(static_cast<int>(n));// revoke(static_cast<int>(m));return 0;
}

输出如下:

走到这里,又引出三个问题。1.T&&是什么        2.forward原理        3.为什么要强转

1.T&&是什么:

        有个东西叫引用折叠

                引用折叠的规则:

                        如果两个引用中至少有一个是左值引用(&),那么结果是左值引用(&

                        如果两个引用都是右值引用(&&),那么结果是右值引用(&&

                比如我们int & &&,那么它会引用折叠变成int & 

                               int && &&,会变成int &&

        引用折叠和模板很像,模板识别参数类型,引用折叠识别引用类型。比如我们template<class T>,那么输入int就会识别成int,输入double就会识别成double。在引用折叠下,输入什么值引用就会识别成什么值引用。

2.forward原理

        forward用于保持原参数的类型,比如我是int&就保持int&,在第二种函数模板中,我们已经说过了,如果不保持原参数的类型,那么t就是一个左值变量,会全部走到左值

3.为什么要强转

        查看完美转发的代码,可以发现有两个错误示例

    //err -- 全部是左值revoke(n);revoke(m);//err -- 全部是右值revoke(static_cast<int>(n));revoke(static_cast<int>(m));

        第一个 -- 在函数调用时,如果你直接传递一个具名变量(无论它是通过左值引用还是右值引用声明的),该变量作为参数传递给函数时总是作为左值传递的。如果我们不强转,那么会被识别左值,这里的强转实际上是告诉函数,我想要传递的类型是什么

        第二个 -- 当一个A类型变量强转为B类型时,实际上是创建了一个B类型的匿名对象来接收一个A类型的变量的值,而匿名对象是右值(将亡值),并且它不具名,所以会被识别成右值(只有具名变量才会默认作为左值传递)

        

相关文章:

C++完美转发(适合小白)

我们知道&#xff0c;C中有左值引用和右值引用&#xff0c;首先我们要知道什么是左值什么是右值。 左值&#xff1a;表达式结束后依然存在的持久对象。左值可以出现在赋值语句的左边或右边。例如&#xff0c;变量和函数返回的引用都是左值。左值通常有持久的地址&#xff0c;可…...

如何创建自己的 Spring Boot Starter 并为其编写单元测试

当我们想要封装一些自定义功能给别人使用的时候&#xff0c;创建Spring Boot Starter的形式是最好的实现方式。如果您还不会构建自己的Spring Boot Starter的话&#xff0c;本文将带你一起创建一个自己的Spring Boot Starter。 快速入门 创建一个新的 Maven 项目。第三方封装的…...

C++ :STL中deque的原理

deque的结构类似于哈希表&#xff0c;使用一个指针数组存储固定大小的数组首地址&#xff0c;当数据分布不均匀时将指针数组内的数据进行偏移&#xff0c;桶不够用的时候会像vector一样扩容然后将之前数组中存储的指针拷贝过来&#xff0c;从原理可以看出deque的性能是非常高的…...

AttributeError: ‘Namespace‘ object has no attribute ‘EarlyStopping‘

报错原因 这个报错信息表明在Python脚本train.py中尝试访问命令行参数args.EarlyStopping时出错&#xff0c;具体错误是AttributeError: Namespace对象没有名为EarlyStopping的属性。 在Python的argparse模块中&#xff0c;当我们通过命令行传递参数并解析时&#xff0c;解析…...

深度学习pytorch——卷积神经网络(持续更新)

计算机如何解析图片&#xff1f; 在计算机的眼中&#xff0c;一张灰度图片&#xff0c;就是许多个数字组成的二维矩阵&#xff0c;每个数字就是此点的像素值&#xff08;图-1&#xff09;。在存储时&#xff0c;像素值通常位于[0, 255]区间&#xff0c;在深度学习中&#xff0…...

【edge浏览器无法登录某些网站,以及迅雷插件无法生效的解决办法】

edge浏览器无法登录某些网站&#xff0c;以及迅雷插件无法生效的解决办法 edge浏览器无法登录某些网站&#xff0c;但chrome浏览器可以登录浏览器插件无法使用&#xff0c;比如迅雷如果重装插件重装浏览器重装迅雷后仍然出现问题 edge浏览器无法登录某些网站&#xff0c;但chro…...

OpenHarmony无人机MAVSDK开源库适配方案分享

MAVSDK 是 PX4 开源团队贡献的基于 MavLink 通信协议的用于无人机应用开发的 SDK&#xff0c;支持多种语言如 C/C、python、Java 等。通常用于无人机间、地面站与通信设备的消息传输。 MAVLink 是一种非常轻量级的消息传递协议&#xff0c;用于与无人机&#xff08;以及机载无…...

模型训练----parser.add_argument添加配置参数

现在需要配置参数来达到修改训练的方式&#xff0c;我现在需要新建一个参数来开关wandb的使用。 首先就是在def parse_option():函数里添加上你要使用的变量名 parser.add_argument("--open_wandb",type bool,defaultFalse,helpopen wandb) 到config文件里增加你的…...

数字未来:探索 Web3 的革命性潜力

在当今数字化的时代&#xff0c;Web3作为互联网的新兴范式正逐渐崭露头角&#xff0c;引发了广泛的关注和探讨。本文将深入探索数字未来中Web3所蕴含的革命性潜力&#xff0c;探讨其对社会、经济和技术的深远影响。 1. Web3&#xff1a;数字世界的下一个阶段 Web3是一个正在崛…...

群晖NAS使用Docker部署大语言模型Llama 2结合内网穿透实现公网访问本地GPT聊天服务

文章目录 1. 拉取相关的Docker镜像2. 运行Ollama 镜像3. 运行Chatbot Ollama镜像4. 本地访问5. 群晖安装Cpolar6. 配置公网地址7. 公网访问8. 固定公网地址 随着ChatGPT 和open Sora 的热度剧增,大语言模型时代,开启了AI新篇章,大语言模型的应用非常广泛&#xff0c;包括聊天机…...

[选型必备基础信息] 存储器

存储芯片根据断电后是否保留存储的信息可分为易失性存储芯片&#xff08;RAM&#xff09;和非易失性存储芯片&#xff08;ROM&#xff09;。 简单说&#xff0c;存储类IC分为 ROM和RAM ROM&#xff1a;EEPROM / Flash / eMMC RAM&#xff1a;SRAM/SDRAM/DDR2/DDR3/DDR4/DDR5…...

C++——C++11线程库

目录 一&#xff0c;线程库简介 二&#xff0c;线程库简单使用 2.1 传函数指针 ​编辑 2.2 传lamdba表达式 2.3 简单综合运用 2.4 线程函数参数 三&#xff0c;线程安全问题 3.1 为什么会有这个问题&#xff1f; 3.2 锁 3.2.1 互斥锁 3.2.2 递归锁 3.3 原子操作 3…...

机器学习 | 线性判别分析(Linear Discriminant Analysis)

1 机器学习中的建模 1.1 描述性建模 以方便的形式给出数据的主要特征&#xff0c;实质上是对数据的概括&#xff0c;以便在大量的或有噪声的数据中仍能观察到重要特征。重在认识数据的主要概貌&#xff0c;理解数据的重要特征。 Task&#xff1a;聚类分析&#xff0c;数据降…...

TypeScript-数组、函数类型

1.数组类型 1.1类型 方括号 let arry:number[][5,2,0,1,3,1,4] 1.2 数组泛型 let arry2:Array<number>[5,2,0,1,3,1,4] 1.3接口类型 interface makeArryRule{[index:number]:number }let arry3:makeArryRule[5,2,0,1,3,1,4] 1.4伪数组 说明&#xff1a; argument…...

Python深度学习034:cuda的环境如何配置

文章目录 1.安装nvidia cuda驱动CMD中看一下cuda版本:下载并安装cuda驱动2.创建虚拟环境并安装pytorch的torch_cuda3.测试附录1.安装nvidia cuda驱动 CMD中看一下cuda版本: 注意: 红框的cuda版本,是你的显卡能装的最高的cuda版本,所以可以选择低于它的版本。比如我的是11…...

【论文笔记】Text2QR

论文&#xff1a;Text2QR: Harmonizing Aesthetic Customization and Scanning Robustness for Text-Guided QR Code Generation Abstract 二维码通常包含很多信息但看起来并不美观。stable diffusion的出现让平衡扫描鲁棒性和美观变为可能。 为了保证美观二维码的稳定生成&a…...

【ReadPapers】A Survey of Large Language Models

LLM-Survey的llm能力和评估部分内容学习笔记——思维导图 思维导图 参考资料 A Survey of Large Language Models论文的github仓库...

站群CMS系统

站群CMS系统是一种用于批量建立和管理网站的内容管理系统&#xff0c;它能够帮助用户快速创建大量的网站&#xff0c;并实现对这些网站的集中管理。以下是三个在使用广泛的站群CMS系统&#xff0c;它们各具特色&#xff0c;可以满足不同用户的需求。 1. Z-BlogPHP Z-BlogPHP是…...

landsat8数据产品说明

1、下载数据用户手册 手册下载网址&#xff0c;搜索landsat science关键词&#xff0c;并点击到官网下载。 2、用户手册目录 3、landsat8数据产品说明 具体说明在手册的第四章&#xff0c;4.1.4数据产品章节&#xff0c;具体描述如下&#xff1a; 英文意思&#xff1a; L8 的…...

Golang 内存管理和垃圾回收底层原理(二)

一、这篇文章我们来聊聊Golang内存管理和垃圾回收&#xff0c;主要注重基本底层原理讲解&#xff0c;进一步实战待后续文章 垃圾回收&#xff0c;无论是Java 还是 Golang&#xff0c;基本的逻辑都是基于 标记-清理 的&#xff0c; 标记是指标记可能需要回收的对象&#xff0c…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

深入浅出Diffusion模型:从原理到实践的全方位教程

I. 引言&#xff1a;生成式AI的黎明 – Diffusion模型是什么&#xff1f; 近年来&#xff0c;生成式人工智能&#xff08;Generative AI&#xff09;领域取得了爆炸性的进展&#xff0c;模型能够根据简单的文本提示创作出逼真的图像、连贯的文本&#xff0c;乃至更多令人惊叹的…...

Sklearn 机器学习 缺失值处理 获取填充失值的统计值

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...