c++可变参数详解

目录

引言

 库的基本功能 

va_start 宏:

va_arg 宏

va_end 宏

va_copy 宏

使用  处理可变参数代码

C++11可变参数模板

基本概念

sizeof... 运算符

包扩展


引言

        在C++编程中,处理不确定数量的参数是一个常见的需求。为了支持这种需求,C标准库提供了 <stdarg.h> 头文件,其中定义了一组宏和类型,用于处理不定参数函数。C++继承了C语言的可变参数机制,使用了stdarg.h提供的宏来处理不确定数量的参数。其原理基于栈的推入和弹出过程,不需要明确参数数量。此外,C++提供了可变参数机制,让我们能够创建接收任意数量参数的函数。这一特性在许多实际应用中非常有用,比如日志记录、函数重载等。

<stdarg.h> 库的基本功能 

<stdarg.h> 库包含以下主要部分:

va_start 宏:

用于初始化 va_list 变量,其基本语法如下:

void va_start(va_list ap, last);
  • apva_list 变量。
  • last:最后一个确定的参数,后面的参数是可变参数。

va_arg 宏

 va_arg 宏用于访问可变参数列表中的下一个参数,其基本语法如下:

type va_arg(va_list ap, type);
  • apva_list 变量。
  • type:要访问的参数的类型。

va_end 宏
 

  va_end 宏用于结束 va_list 变量的访问,其基本语法如下:

void va_end(va_list ap);
  •   ap:va_list 变量。


va_copy 宏

  va_copy 宏用于复制 va_list 变量,其基本语法如下:

void va_copy(va_list dest, va_list src);
  • dest:目标 va_list 变量。
  • src:源 va_list 变量。

使用 <stdarg.h> 处理可变参数代码

        示例中,print_args接收一个格式字符串,然后根据格式字符(i表示整数,d表示双精度浮点数)解析后面的参数。

#include <iostream>
#include <cstdarg>void print_args(const char* fmt, ...)
{va_list args;va_start(args, fmt);while (*fmt != '\0') {if (*fmt == 'i') {int i = va_arg(args, int);std::cout << "int: " << i << std::endl;} elseif (*fmt == 'd') {double d = va_arg(args, double);std::cout << "double: " << d << std::endl;}++fmt;}va_end(args);
}int main()
{print_args("ddii", 0.618,3.14, 7, 9);return 0;
}
//double: 0.618 double: 3.14 int: 7 int: 9

C++11可变参数模板

基本概念

        C++11通过模板提供了类型安全且灵活的可变参数机制。可以通过递归模板来处理不同类型的参数,避免了手动处理类型的麻烦。也就是支持可变数量参数的函数模板和类模板,可变数目的参数被称为参数包。

参数包有两种类型:

  • 模板参数包,表示零或多个模板参数,使用class...或typename...关键字声明。
  • 函数参数包,表示零个或多个函数参数,使用类型名后跟...表示。
template<class ...Arg> void Func(Arg... arg) {}
template<class ...Arg> void Func(Arg... arg) {}
template<class ...Arg> void Func(Arg... arg) {}

         我们用省略号...来指出一个模板参数或函数参数的表示一个包,在模板参数列表中,class...或typename...指出接下来的参数表示零或多个类型列表;在函数参数列表中,类型名后面跟...指出接下来表示零或多个形参对象列表。可变参数模板的原理跟模板类似,本质还是去实例化对应类型和个数的多个函数。

sizeof... 运算符

sizeof...运算符来计算参数包中参数的个数。

template <class ...Arg>
void PrintArgNum(Arg&&... arg)
{cout << sizeof...(arg)<<"个参数包" << endl;
}int main()
{double a = 3.14;PrintArgNum();PrintArgNum(a);//一个参数PrintArgNum(1, string("241564132"));//两个参数return 0;
}

        编译本质会结合引用折叠规则实例化出以下三个函数,在类型泛化基础上叠加了数量变化,让泛型编程更加灵活。

void Print();
void Print(double&& arg1);
void Print(int&& arg1, string&& arg2);

包扩展

        对于一个参数包,我们除了计算它的参数个数,还可以对它进行包扩展。我们还要提供用于每个扩展元素的模式,扩展一个包就是将他分解为构成的元素,对每个元素应用模式,获得扩展后的列表。我们通过在模式的右边放省略号(...)来触发扩展操作。

//参数包是0个时,直接匹配这个函数
void ShowList()
{cout<< endl;
}template<class T,class ...Arg>
void ShowList(T&& val,Arg&&... arg)
{cout << val << endl;//arg是N个参数的参数包,调用Printf,参数包的第一个传给val,剩下N-1个传给参数包,ShowList(arg...);
}
template <class ...Arg>
void Print(Arg&&... arg)
{cout << sizeof...(arg)<<"个参数包" << endl;ShowList(arg...);
}int main()
{double x = 3.14;Print();Print(11.1);//一个参数Print(1, string("bjkbhv"));//两个参数Print(12.55, string("9jjug7"), x);//三个参数return 0;
}

        实际上是通过递归展开来实现的,当参数包为空时就会调用 void ShowList(),同时终止递归

递归时,T接受传来参数包的第一个参数类型,arg接受其余的参数类型,以此往复。

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

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

相关文章

【自学嵌入式(8)天气时钟:天气模块开发、主函数编写】

天气时钟&#xff1a;天气模块开发、主函数编写 I2C协议和SPI协议I2C&#xff08;Inter-Integrated Circuit&#xff09;SPI&#xff08;Serial Peripheral Interface&#xff09; 天气模块心知天气预报使用HTTPClient类介绍主要功能常用函数注意事项 JSON介绍deserializeJson函…

SpringBoot的配置(配置文件、加载顺序、配置原理)

文章目录 SpringBoot的配置(配置文件、加载顺序、配置原理)一、引言二、配置文件1、配置文件的类型1.1、配置文件的使用 2、多环境配置 三、加载顺序四、配置原理五、使用示例1、配置文件2、配置类3、控制器 六、总结 SpringBoot的配置(配置文件、加载顺序、配置原理) 一、引言…

深度学习的应用场景及常用技术

深度学习作为机器学习的一个重要分支&#xff0c;在众多领域都有广泛的应用&#xff0c;以下是一些主要的应用场景及常用技术。 1.应用场景 1. 计算机视觉 图像分类 描述&#xff1a;对图像中的内容进行分类&#xff0c;识别出图像中物体所属的类别。例如&#xff0c;在安防领…

政务行业审计文件大数据高速报送解决方案

随着信息技术的快速发展&#xff0c;电子政务迎来了新的升级浪潮。国家相继出台了一系列信息化发展战略规划&#xff0c;如《国家信息化发展战略纲要》、《“十三五”国家信息化规划》等&#xff0c;这些政策为政务信息化工作指明了方向。 然而&#xff0c;在实际操作中&#x…

GMSL 明星产品之 MAX96724

上一篇文章中&#xff0c;我们介绍了摄像头侧 GMSL 加串器 MAX96717. 今天我们来介绍下 GMSL 解串器明星产品 MAX96724&#xff1a; 可将四路 GMSL™2/1 输入转换为 1 路、2 路或 4 路 MIPI D-PHY 或 C-PHY 输出。该器件支持通过符合 GMSL 通道规范的 50Ω 同轴电缆或 100Ω 屏…

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_strerror_init()函数

目录 ngx_strerror_init()函数声明 ngx_int_t 类型声明定义 intptr_t 类型 ngx_strerror_init()函数实现 NGX_HAVE_STRERRORDESC_NP ngx_strerror_init()函数声明 在 nginx.c 的开头引入了: #include <ngx_core.h> 在 ngx_core.h 中引入了 #include <ngx_er…

机器学习--概览

一、机器学习基础概念 1. 定义 机器学习&#xff08;Machine Learning, ML&#xff09;&#xff1a;通过算法让计算机从数据中自动学习规律&#xff0c;并利用学习到的模型进行预测或决策&#xff0c;而无需显式编程。 2. 与编程的区别 传统编程机器学习输入&#xff1a;规…

MySQL5.5升级到MySQL5.7

【卸载原来的MySQL】 cmd打开命令提示符窗口&#xff08;管理员身份&#xff09;net stop mysql&#xff08;先停止MySQL服务&#xff09; 3.卸载 切换到原来5.5版本的bin目录&#xff0c;输入mysqld remove卸载服务 测试mysql -V查看Mysql版本还是5.5 查看了环境变量里的…

java SSM框架 商城系统源码(含数据库脚本)

商城购物功能&#xff0c;项目代码&#xff0c;mysql脚本&#xff0c;html等静态资源在压缩包里面 注册界面 登陆界面 商城首页 文件列表 shop/.classpath , 1768 shop/.project , 1440 shop/.settings/.jsdtscope , 639 shop/.settings/org.eclipse.core.resources.prefs , …

【PyTorch】3.张量类型转换

个人主页&#xff1a;Icomi 在深度学习蓬勃发展的当下&#xff0c;PyTorch 是不可或缺的工具。它作为强大的深度学习框架&#xff0c;为构建和训练神经网络提供了高效且灵活的平台。神经网络作为人工智能的核心技术&#xff0c;能够处理复杂的数据模式。通过 PyTorch&#xff0…

Shell特殊状态变量以及常用内置变量总结

目录 1. 特殊的状态变量 1.1 $?&#xff08;上一个命令的退出状态&#xff09; 1.2 $$&#xff08;当前进程的 PID&#xff09; 1.3 $!&#xff08;后台进程的 PID&#xff09; 1.4 $_&#xff08;上一条命令的最后一个参数&#xff09; 2.常用shell内置变量 2.1 echo&…

用 HTML、CSS 和 JavaScript 实现抽奖转盘效果

顺序抽奖 前言 这段代码实现了一个简单的抽奖转盘效果。页面上有一个九宫格布局的抽奖区域&#xff0c;周围八个格子分别放置了不同的奖品名称&#xff0c;中间是一个 “开始抽奖” 的按钮。点击按钮后&#xff0c;抽奖区域的格子会快速滚动&#xff0c;颜色不断变化&#xf…

小白零基础--CPP多线程

进程 进程就是运行中的程序线程进程中的进程 1、C11 Thread线程库基础 #include <iostream> #include <thread> #include<string>void printthread(std::string msg){std::cout<<msg<<std::endl;for (int i 0; i < 1000; i){std::cout<…

deepseek的两种本地使用方式

总结来说 ollama是命令行 GPT4ALL桌面程序。 然后ollamaAnythingLLM可以达到桌面或web的两种接入方式。 一. ollama和deepseek-r1-1.5b和AnythingLLM 本文介绍一个桌面版的deepseek的本地部署过程&#xff0c;其中ollama可以部署在远程。 1. https://www.cnblogs.com/janeysj/p…

DDD 和 TDD

领域驱动设计&#xff08;DDD&#xff09; DDD 是一种软件开发方法&#xff0c;强调通过与领域专家的密切合作来构建一个反映业务逻辑的模型。其核心思想是将业务逻辑和技术实现紧密结合&#xff0c;以便更好地解决复杂的业务问题。 DDD 的关键概念&#xff1a; 1. 领域模型 …

修复fstab文件引起的系统故障

进入系统救援模式&#xff0c;修复故障 通过光盘启动系统&#xff0c;进入救援模式 点击虚拟机....>电源....>打开电源时进入固件进入BIOS程序 按号把光盘调到最前面&#xff08;优先使用光盘启动&#xff09; 按F10保存退出 重启选择最后一个进行排错 选择第二项 救援c…

深入核心:一步步手撕Tomcat搭建自己的Web服务器

介绍&#xff1a; servlet&#xff1a;处理 http 请求 tomcat&#xff1a;服务器 Servlet servlet 接口&#xff1a; 定义 Servlet 声明周期初始化&#xff1a;init服务&#xff1a;service销毁&#xff1a;destory 继承链&#xff1a; Tomcat Tomcat 和 servlet 原理&#x…

傅里叶分析之掐死教程

https://zhuanlan.zhihu.com/p/19763358 要让读者在不看任何数学公式的情况下理解傅里叶分析。 傅里叶分析 不仅仅是一个数学工具&#xff0c;更是一种可以彻底颠覆一个人以前世界观的思维模式。但不幸的是&#xff0c;傅里叶分析的公式看起来太复杂了&#xff0c;所以很多…

Python-基于PyQt5,wordcloud,pillow,numpy,os,sys等的智能词云生成器(最终版)

前言:日常生活中,我们有时后就会遇见这样的情形:我们需要将给定的数据进行可视化处理,同时保证呈现比较良好的量化效果。这时候我们可能就会用到词云图。词云图(Word cloud)又称文字云,是一种文本数据的图片视觉表达方式,一般是由词汇组成类似云的图形,用于展示大量文…

【Linux系统】信号:认识信号 与 信号的产生

信号快速认识 1、生活角度的信号 异步&#xff1a;你是老师正在上课&#xff0c;突然有个电话过来资料到了&#xff0c;你安排小明过去取资料&#xff0c;然后继续上课&#xff0c;则小明取资料这个过程就是异步的 同步&#xff1a;小明取快递&#xff0c;你停下等待小明回来再…