赞
踩
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函数处理后,再解包,然后递归
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。