当前位置:   article > 正文

C++ 可变参数模板_c++ 可变模板头文件

c++ 可变模板头文件

可变参数函数

C++中可变参数的函数是从C中继承而来,可变参数的函数是指函数的参数个数可变,参数类型不定的函数。

可变参数函数实现原理

函数的调用的参数会进行压栈处理,而对参数的压栈是从右到左进行压栈。而参数和参数之间存放是连续的,也就是说,只要知道第一个参数的地址和类型,以及其他参数的类型,就可以获取各个参数的地址。

int printf(const char* format, ...);
printf("%d and % c",a,b);
  • 1
  • 2

这里的a是int型,b是char型。printf()有3个参数,一个const char*,一个是int,一个是char。所以参数压栈的顺序就是先将b入栈,再将a入栈,最后是format入栈,由于栈是向下(低地址)生长的,所以在知道了format的地址之后,所有的参数地址都可以计算出来。

声明和定义

可变参数函数的声明很简单,对于不定参数部分用“…”表示即可。但是实现原理可以看到,第一个的参数的地址是必须提供的,也就是可变参数必须至少包含一个参数,这个参数用来寻址,实现对所有参数的访问。

处理可变参数的标准宏

/可变参数标准宏头文件
#include "stdarg.h"
 
//申明va_list数据类型变量pvar,该变量访问变长参数列表中的参数。
va_list pvar;
 
//宏va_start初始化变长参数列表。pvar是va_list型变量,记载列表中的参数信息。
//parmN是省略号"..."前的一个参数名,va_start根据此参数,判断参数列表的起始位置。
va_start(pvar, parmN);
 
//获取变长参数列表中参数的值。pvar是va_list型变量,type为参数值的类型,也是宏va_arg返回数值的类型。
//宏va_arg执行完毕后自动更改对象pvar,将其指向下一个参数。
va_arg(pvar, type);
 
//关闭本次对变长参数列表的访问。
va_end(pvar);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

示例

第一个参数指定了要计算的值的个数。

#include "stdarg.h"
using namespace std;
 
int sum(int count, ...)
{
	int sum_value=0;
 
	va_list args;
	va_start(args,count);
	while(count--)
	{
		sum_value+=va_arg(args,int);
	}
	va_end(args);
 
	return sum_value;
}
 
int main(int argc, _TCHAR* argv[])
{
	cout<<sum(5,1,2,3,4,5);//输出15
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

可变参数模板

对于可变参数模板,其将包含至少一个模板参数包,模板参数包是可以接收0个或者多个参数的模板参数。

使用规则

template<typename ... Types>
class Tuple
{};

Tuple<> t0;
Tuple<int> t1;
Tuple<int, string> t2;
// Tuple<0> error;  0 is not a type
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

可变参数函数模板实例

// 用于终止迭代的基函数
template<typename T>
void processValues(T &&arg)
{
	//左值引用无法引用字面常量,所以此处使用通用引用和forward实现完美转发
    handleValue(std::forward<T>(arg));
}

// 可变参数函数模板
template<typename T, typename ... Ts>
void processValues(T&& arg, Ts&& ... args)
{
    handleValue(std::forward<T>(arg));
    processValues(std::forward<Ts>(args) ...); // 先使用forward函数处理后,再解包,然后递归
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/577021
推荐阅读
相关标签
  

闽ICP备14008679号