【C++】C语言可变函数参数 | C++11可变参数模板

文章目录

      • C语言的可变函数参数
        • 遍历`va_list`逐个取出参数
      • C++可变模板参数
        • 递归展开模板参数包示例代码
        • 逗号表达式展开参数包
      • 总结

C++11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板,相比C++98/03,类模版和函数模版中只能含固定数量的模版参数。

C语言的可变函数参数和C++的可变参数模板有相似之处

C语言的可变函数参数

C语言中,可变函数参数是通过stdarg.h头文件中的宏和函数来实现的。标准库中的printf、scanf,就是用可变函数参数的原理实现的。

  • va_list: 定义一个变量,用于存储可变参数的信息。
  • va_start(va_list ap, last_arg): 初始化va_list,使其指向可变参数列表中的第一个参数。
  • va_arg(va_list ap, type): 获取可变参数列表中的下一个参数的值,同时将va_list指向下一个参数。
  • va_end(va_list ap): 清理va_list,使其无效。
遍历va_list逐个取出参数
#include <stdarg.h>
#include <stdio.h>int sum(int count, ...) 
{int result = 0;va_list args;va_start(args, count);for (int i = 0; i < count; ++i) {result += va_arg(args, int);}va_end(args);return result;
}int main() 
{int total = sum(3, 10, 20, 30);printf("Sum: %d\n", total);return 0;
}

C++可变模板参数

C++中,可变模板参数是通过模板参数包来实现的。

  • Args是一个模板参数包,而args是一个函数形参参数包。
  • 声明一个参数包Args ...args,这个参数包中可以包含0到任意个模板参数。
  • 使用sizeof...(Args),可以 获取模板参数包中的参数数量。

下面是一个简单的可变参数的函数模板:

template <class ...Args>
void ShowList(Args... args)
{}

上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数
包”,它里面包含了0到N(N>=0)个模版参数。我们无法直接获取参数包args中的每个参数的,
只能通过展开参数包的方式来获取参数包中的每个参数,这是使用可变模版参数的一个主要特
点,也是最大的难点,即如何展开可变模版参数。由于语法不支持使用args[i]这样方式获取可变
参数,所以我们的用一些奇招来一一获取参数包的值。

递归展开模板参数包示例代码
  • 利用递归,展开模板参数包,可以在编译时处理不同数量的参数。
#include <iostream>// 递归展开模板参数包
// 递归终止函数
template<typename T>
void print(T value) 
{std::cout << value << std::endl;
}// 展开函数
template<typename T, typename... Args>
void print(T first, Args... args) 
{std::cout << first << ", ";print(args...);
}int main() 
{print(1, 2.5, "Hello", 'a');return 0;
}
逗号表达式展开参数包

如果参数包中各个参数的类型都是整型,那么也可以把这个参数包放到列表当中初始化这个整型数组,此时参数包中参数就放到数组中了:

//展开函数
template<class ...Args>
void ShowList(Args... args)
{int arr[] = { args... }; //列表初始化//打印参数包中的各个参数for (auto e : arr){cout << e << " ";}cout << endl;
}int main()
{ShowList(1, 2, 3, 4);             //正确ShowList("hello", 1, "world", 2); //错误:数组arr只能存放相同类型元素intShowList();                       //错误:不能分配大小为0的数组return 0;
}

虽然我们不能用不同类型的参数去初始化一个整型数组,但我们可以借助逗号表达式。

  • 逗号表达式会从左到右依次计算各个表达式,并且将最后一个表达式的值作为返回值进行返回。
  • 将逗号表达式的最后一个表达式设置为一个整型值,确保逗号表达式返回的是一个整型值。
  • 将处理参数包中参数的动作封装成一个函数,将该函数的调用作为逗号表达式的第一个表达式。
  • {(printarg(args), 0)...}将会展开成{(printarg(arg1),0),(printarg(arg2),0), (printarg(arg3),0), etc... }
  • 这样一来,在执行逗号表达式时就会先调用处理函数处理对应的参数,然后再将逗号表达式中的最后一个整型值作为返回值来初始化整型数组。

比如:

//支持无参调用
void ShowList()
{cout << endl;
}
//处理函数
template<class T>
void PrintArg(const T& t)
{cout << t << " ";
}
//展开函数
template<class ...Args>
void ShowList(Args... args)
{int arr[] = { (PrintArg(args), 0)... }; //列表初始化+逗号表达式cout << endl;
}

总结

  • C语言使用stdarg.h来实现可变函数参数,通过va_listva_startva_argva_end宏进行操作。
  • C++使用模板参数包来实现可变模板参数,可以利用递归、逗号表达式展开参数包处理不同数量的参数。

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

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

相关文章

暑期宅家?计算机专业必看的8部电影!一定要安利给你们!

代码编程看上去枯燥乏味&#xff0c;但也是艺术的&#xff0c;感性的&#xff0c;计算机编程的许多概念被应用于电影中&#xff0c;其中有些非常之酷炫&#xff0c;它们甚至能帮助开发人员理解一些编程概念。 所以今天学姐来给大家推荐几部心中top级的编程人必看电影&#xff0…

[C++]C++ 中的 #if 、#ifndef 和 #ifdef

#ifndef 和 #ifdef 是一种宏定义判断&#xff0c;作用是防止多重定义。#ifndef 是 if not define 的简写&#xff0c;#ifdef 是 if define 的简写。 使用格式如下&#xff1a; #if (判断条件) 程序段1 #else 程序段2 #endif#ifdef 标识符 程序段1 #else 程序段2 #endif#ifnde…

nginx(二)

nginx的验证模块 输入用户名和密码 第一步先下载httpd 这个安装包 第二步编辑子配置文件 然后去网页访问192.168.68.3/admin/ 连接之后&#xff0c;会出现404&#xff0c;404出现是因为没给网页写页面 如果要写页面&#xff0c;则在/opt/html&#xff0c;建立一个admin&#x…

max_element和min_element使用

头文件 #include<alorithm> 作用 用于返回数组或容器中最值元素(最小值、最大值)&#xff0c;值和下标。 使用举例 #include<iostream> #include<vector> #include<algorithm> using namespace std; int main() {/*数组初始化*/vector<int>…

软件设计师软考题目解析05 --每日五题

想说的话&#xff1a;要准备软考了。0.0&#xff0c;其实我是不想考的&#xff0c;但是吧&#xff0c;由于本人已经学完所有知识了&#xff0c;只是被学校的课程给锁在那里了&#xff0c;不然早找工作去了。寻思着反正也无聊&#xff0c;就考个证玩玩。 本人github地址&#xf…

微信小程序返回上一级页面并自动刷新数据

文章目录 前言一、获取小程序栈二、生命周期触发总结 前言 界面由A到B&#xff0c;在由B返回A&#xff0c;触发刷新动作 一、获取小程序栈 界面A代码 shuaxin(){//此处可进行接口请求从而实现更新数据的效果console.log("刷新本页面数据啦")},界面B代码 // 返回触…

spring缓存的使用

Spring缓存使用 缓存注解 对于Spring&#xff0c;缓存组件例如EhCache是可拔插的&#xff0c;而缓存注解是通用的。 Cacheable 标记在方法或者类上&#xff0c;标识该方法或类支持缓存。Spring调用注解标识方法后会将返回值缓存到redis&#xff0c;以保证下次同条件调用该方…

C++mciSendString开发软件:音乐播放器2.0

目录 目录 目录 回顾上集代码 开始更改! 1、增加色彩特效 效果 2、增加命令行 初始化界面 获取时长 结构体 设置时长 退出 切换音乐 ......(没用的一堆玩意儿) 完整代码 回顾上集代码 #include <Button.h> #include <heker.h> #include <ARTTEXT.h> …

StopWatch的使用

StopWatch的使用 【一】简介【1】不使用StopWatch的案例【2】使用StopWatch的案例 【二】源码分析【1】查看源码【2】StopWatch优缺点&#xff1a; 【一】简介 stopWatch是org.springframework.util包下的一个工具类&#xff0c;使用它可直观的输出代码执行耗时&#xff0c;以…

MySQL--索引结构

索引-索引结构 1. 概述2. 二叉树3. B-Tree4. BTree5. Hash 1. 概述 MySQL的索引是在存储引擎层实现的&#xff0c;不同的存储引擎有不同的索引结构&#xff0c;主要包含以下几种&#xff1a; 上述是MySQL中所支持的所有的索引结构&#xff0c;下面展示不同的存储引擎对于索引…

JDK下载安装

资源展示 安装说明 傻瓜式安装&#xff0c;下一步即可。建议&#xff1a;安装路径不要有中文或者空格等特殊符号。本套课程会同时安装JDK8 和 JDK17&#xff0c;并以JDK17为默认版本进行讲解。 安装步骤 &#xff08;1&#xff09;双击jdk-17_windows-x64_bin.exe文件&#…

【Eureka详细讲解】

Eureka介绍和使用 1. Eureka 介绍2. Eureka 的主要特点3. 使用3.1 设置 Eureka Server3.2 设置 Eureka Client3.3 Eureka Server 高可用配置 1. Eureka 介绍 Eureka 是由 Netflix 开源的一种服务发现解决方案&#xff0c;它是 Netflix OSS 套件中的一个组件&#xff0c;经常用…

8-pytorch-损失函数与反向传播

b站小土堆pytorch教程学习笔记 根据loss更新模型参数 1.计算实际输出与目标之间的差距 2.为我们更新输出提供一定的依据&#xff08;反向传播&#xff09; 1 MSEloss import torch from torch.nn import L1Loss from torch import nninputstorch.tensor([1,2,3],dtypetorch.fl…

(只需三步)免费使用知网的攻略

通过浙江图书馆可以进入知网&#xff0c;并且查看与下载都是免费的。 &#xff08;只需要三步&#xff0c;很简单的。&#xff09; 第一步&#xff1a;注册浙江图书馆账号 打开zfb&#xff0c;搜索“浙江图书馆”小程序&#xff0c;进入个人中心->办理读者证&#xff0c;…

不同尺度下的网络控制方式

《三国演义》和《长安十二时辰》有什么不同&#xff1f; 关羽败走麦城&#xff0c;远在千里之外的刘备收到两个信号&#xff0c;一个需要 “星夜驰援”&#xff0c;紧接着 “二弟休矣”&#xff0c;三国的故事在东亚大陆展开&#xff0c;地理尺度巨大&#xff0c;星夜不星夜其…

PHP语言检测用户输入密码及调用Python脚本

现在有一份计算流体力学N-S方程的Python脚本&#xff0c;想要在用户登录网站后可以可以运行该脚本&#xff0c;然后将脚本运行后绘制的图片显示在用户网页上。 建一个名为N_S.py的python脚本文件&#xff0c;这个脚本在生成图像后会自行关闭&#xff0c;随后将图片保存在指定的…

一篇超级最全的python基础篇

1.数据类型和变量 Python使用缩进来组织代码块,一般使用4个空格的缩进.使用#来注释一行,其他每一行都是一个语句,当语句以冒号:结尾时,缩进的语句视为代码块.Python对大小写敏感. 1.1 整数 Python可以处理任意大小的整数,包括负整数,写法与数学上写法一致,例如:-100.如果用十六…

【文本编辑器,哪款适合你?】讲解

文本编辑器&#xff0c;哪款适合你? 文本编辑器介绍 文本编辑器介绍 电脑使用者在选择文本编辑器时&#xff0c;应该考虑以下几个方面&#xff1a; 需求&#xff1a;你是需要进行基本的文字处理工作&#xff0c;比如写作业或者制作报告&#xff0c;还是需要使用到高级功能&am…

BIO实战、NIO编程与直接内存、零拷贝深入辨析

BIO实战、NIO编程与直接内存、零拷贝深入辨析 长连接、短连接 长连接 socket连接后不管是否使用都会保持连接状态多用于操作频繁&#xff0c;点对点的通讯&#xff0c;避免频繁socket创建造成资源浪费&#xff0c;比如TCP 短连接 socket连接后发送完数据后就断开早期的http服…

简单上手若依框架

简介 若依是一个基于SpringBoot&#xff0c;Shiro&#xff0c;Mybatis的权限后台管理系统官网文档&#xff1a;介绍 | RuoYi源码 前后端不分离 RuoYi: &#x1f389; 基于SpringBoot的权限管理系统 易读易懂、界面简洁美观。 核心技术采用Spring、MyBatis、Shiro没有任何其它重…