C++ 可变参数模板

可变参数函数

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

可变参数函数实现原理

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

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

这里的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);

示例

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

#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
}

可变参数模板

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

使用规则

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

Tuple<> t0;
Tuple<int> t1;
Tuple<int, string> t2;
// Tuple<0> error;  0 is not a type

可变参数函数模板实例

// 用于终止迭代的基函数
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函数处理后,再解包,然后递归
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值