【C++】可变参数模板使用总结(简洁易懂,详细,含代码演示)

前言

大家好吖,欢迎来到 YY 滴C++系列 ,热烈欢迎! 本章主要内容面向接触过C++的老铁
主要内容含:
在这里插入图片描述

欢迎订阅 YY滴C++专栏!更多干货持续更新!以下是传送门!

  • YY的《C++》专栏
  • YY的《C++11》专栏
  • YY的《Linux》专栏
  • YY的《数据结构》专栏
  • YY的《C语言基础》专栏
  • YY的《初学者易错点》专栏
  • YY的《小小知识点》专栏

目录

  • 一.可变参数模板
    • 【1】基本可变参数的函数模板演示:
    • 【2】使用:求函数包的大小——>【...语法】
    • 【3】使用:递归函数方式展开参数包(遍历/打印)演示:
    • 【4】使用注意点:参数包(遍历/打印)是不支持类似数组一样的遍历打印方式
    • 【5】使用:"逗号表达式"方式展开参数包(遍历/打印)演示:(看懂即可)
    • 【6】使用:一般(遍历/打印)展开参数包的最常用方式——>【...语法】

一.可变参数模板

【1】基本可变参数的函数模板演示:

  • 下面的参数 args 前面有省略号,所以它就是一个 可变模版参数
  • 我们把 带省略号的参数称为“参数包” ,它里面包含了0到N(N>=0)个模板参数
  • 用可变模版参数的一个主要特点:我们无法直接获取参数包args中的每个参数的,只能通过展开参数包(遍历)的方式来获取参数包中的每个参数【可在第3小点查看详解】
  • 虽然 参数包的底层是 ——> 类似数组的形式存储 ,但是语法不支持使用args[i]这样方式获取可变参数【可在第4小点查看详解】
// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args...args,这个参数包中可以包含0到任意个模板参数。
template <class ...Args>
void ShowList(Args... args)
{}

【2】使用:求函数包的大小——>【…语法】

  • 代码:sizeof...(args)
void ShowList(Args... args)
{cout << sizeof...(args) << endl;
}

【3】使用:递归函数方式展开参数包(遍历/打印)演示:

  • 如下面代码所示:要设计两个函数
  1. 结束条件的函数
  2. 递归函数

分析:

  • 我们可以发现,设计的_ShowList函数的参数是(T val, Args… args)
  • 我们可以这样理解 ,——> 它把参数包的 第一个 拿了出来当作参数T, 剩下的参数包 再整成另一个新的参数包args…
void _ShowList()
{// 结束条件的函数————传空cout << endl;
}template <class T, class ...Args>
void _ShowList(T val, Args... args)
{cout << val << " ";_ShowList(args...);
}//args代表0-N的参数包
template <class ...Args>
void CppPrint(Args... args)
{_ShowList(args...);
}int main()
{CppPrint();CppPrint(1);CppPrint(1, 2);CppPrint(1, 2, 2.2);CppPrint(1, 2, 2.2, string("xxxx"));// ...return 0;
}

【4】使用注意点:参数包(遍历/打印)是不支持类似数组一样的遍历打印方式

  • 参数包不支持如下面代码所示,根据其底层是 类似数组的形式 ,下面代码是想利用数组的方式打印
template <class ...Args>
void ShowList(Args... args)
{cout << sizeof...(args) << endl;// 不支持这样打印for (size_t i = 0; i < sizeof...(args); i++){cout << args[i] << endl;}
}

【5】使用:"逗号表达式"方式展开参数包(遍历/打印)演示:(看懂即可)

  • 我们知道逗号表达式会 按顺序执行逗号前面的表达式
  • 函数中的逗号表达式:(printarg(args), 0),也是按照这个执行顺序,先执行PrintArg(args),再得到逗号表达式的结果0
  • 同时还用到了C++11的另外一个特性——初始化列表, 通过初始化列表来初始化一个变长数组
  • {(printarg(args), 0)…}将会展开成((printarg(arg1),0),(printarg(arg2),0), (printarg(arg3),0), etc… ) ,最终会创建一个元素值都为0的数组int arr[sizeof…(Args)]。
  • 由于是逗号表达式,在创建数组的过程中会先执行逗号表达式前面的部分printarg(args)打印出参数,也就是说在构造int数组的过程中就将参数包展开了, 这个数组的目的 纯粹是为了在数组构造的过程展开参数包
template <class T>
void PrintArg(T t)
{cout << t << " ";
}
//展开函数
template <class ...Args>
void ShowList(Args... args)
{int arr[] = { (PrintArg(args), 0)... };cout << endl;
}
int main()
{ShowList(1);ShowList(1, 'A');ShowList(1, 'A', std::string("sort"));return 0;
}

【6】使用:一般(遍历/打印)展开参数包的最常用方式——>【…语法】

  • 用如下面代码所示构建数组即可:int a[] = { PrintArg(args)...};
void CppPrint()//单独讨论参数为空的清空
{cout << endl;
}template <class T>
int PrintArg(T t)
{cout << t << " ";return 0;
}//args代表0-N的参数包
template <class ...Args>
void CppPrint(Args... args)
{int a[] = { PrintArg(args)...};cout << endl;
}int main()
{CppPrint();CppPrint(1);CppPrint(1, 2);CppPrint(1, 2, 2.2);CppPrint(1, 2, 2.2, string("xxxx"));return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Tomcat日志乱码了怎么处理?

【前言】 tomacat日志有三个地方&#xff0c;分别是Output(控制台)、Tomcat Localhost Log(tomcat本地日志)、Tomcat Catalina Log。 启动日志和大部分报错日志、普通日志都在output打印;有些错误日志&#xff0c;在Tomcat Localhost Log。 三个日志显示区&#xff0c;都可能…

rk3588 之启动

目录 uboot版本配置修改编译 linux版本配置修改编译 启动sd卡启动制作spi 烧录 参考 uboot 版本 v2024.01-rc2 https://github.com/u-boot/u-boot https://github.com/rockchip-linux/rkbin 配置修改 使用这两个配置即可&#xff1a; orangepi-5-plus-rk3588_defconfig r…

插入排序之C++实现

描述 插入排序是一种简单直观的排序算法。它的基本思想是将一个待排序的数据序列分为已排序和未排序两部分&#xff0c;每次从未排序序列中取出一个元素&#xff0c;然后将它插入到已排序序列的适当位置&#xff0c;直到所有元素都插入完毕&#xff0c;即完成排序。 实现思路…

差生文具多之(二): perf

栈回溯和符号解析是使用 perf 的两大阻力&#xff0c;本文以应用程序 fio 的观测为例子&#xff0c;提供一些处理它们的经验法则&#xff0c;希望帮助大家无痛使用 perf。 前言 系统级性能优化通常包括两个阶段&#xff1a;性能剖析和代码优化&#xff1a; 性能剖析的目标是寻…

从mice到missForest:常用数据插值方法优缺点

一、引言 数据插值方法在数据处理和分析中扮演着至关重要的角色。它们可以帮助我们处理缺失数据&#xff0c;使得数据分析更加准确和可靠。数据插值方法被广泛应用于金融、医疗、社会科学等领域&#xff0c;以及工程和环境监测等实际应用中。 在本文中&#xff0c;我们将探讨三…

UNet、U²Net医学图像分割网络

UNet网络结构 对于医学图像的分割任务&#xff0c;这里使用UNet网络实现CT影响的病灶区域分割任务。记一篇学习笔记。 1、UNet网络结构 原始图片大小为(512, 512), 根据CT数据像素值分布的特征&#xff0c;对于image保留[-1024, 1024]范围内的像素&#xff0c;并归一 化处理到…

Android画布Canvas裁剪clipRect,Kotlin

Android画布Canvas裁剪clipRect&#xff0c;Kotlin private fun mydraw() {val originBmp BitmapFactory.decodeResource(resources, R.mipmap.pic).copy(Bitmap.Config.ARGB_8888, true)val newBmp Bitmap.createBitmap(originBmp.width, originBmp.height, Bitmap.Config.A…

kubelet源码学习(一):kubelet工作原理、kubelet启动过程

本文基于Kubernetes v1.22.4版本进行源码学习 1、kubelet工作原理 1&#xff09;、kubelet核心工作 kubelet的工作核心就是一个控制循环&#xff0c;即&#xff1a;SyncLoop&#xff08;图中的大圆圈&#xff09;。而驱动这个控制循环运行的事件&#xff0c;包括&#xff1a;P…

项目管理进阶之序言

背景 可能任何一个程序猿/媛都有一个梦想&#xff0c;立志成为一个技术Leader&#xff0c;带领一个Team&#xff0c;完成一个组织中重要的Project。 有些人天赋异禀&#xff0c;光彩夺目&#xff0c;从小已形成的某些特质&#xff0c;足以让他/她胜任这个领域&#xff0c;我们…

【贪心】买卖股票的最佳时机含手续费

/** 贪心&#xff1a;每次选取更低的价格买入&#xff0c;遇到高于买入的价格就出售(此时不一定是最大收益)。* 使用buy表示买入股票的价格和手续费的和。遍历数组&#xff0c;如果后面的股票价格加上手续费* 小于buy&#xff0c;说明有更低的买入价格更新buy。如…

【c++】string类的使用

目录 一、标准库中的string类 1、简单介绍string类 2、string类的常用接口注意事项 2.1、string类对象的常用构造 2.2、string类对象的容量操作 2.3、string类对象的访问及遍历操作 2.4、string类对象的修改操作 二、string类的模拟实现 一、标准库中的string类 1、简…