2、省略符形参
函数可以用省略符形参”…“表示不定参数部分,省略符形参只能出现在形参列表的最后一个位置,它的形式如下:
void foo(parm_list, ...);
// 典型例子
int printf(const char* format, ...)
省略符形参应该仅仅用于C和C++通用的类型,因为大多数类类型的对象在传递给省略符形参时都无法正确拷贝。下面是<cstdarg>头文件中的几个宏定义:
#include<cstdarg> // C中是<stdarg.h>
// va_list是一种数据类型,args用于持有可变参数。
// 定义typedef char* va_list;
va_list args;
// 调用va_start并传入两个参数:第一个参数为va_list类型的变量
// 第二个参数为"..."前最后一个参数名
// 将args初始化为指向第一个参数(可变参数列表)
va_start(args, paramN);
// 检索参数,va_arg的第一个参数是va_list变量,第二个参数指定返回值的类型
// 每一次调用va_arg会获取当前的参数,并自动更新指向下一个可变参数。
va_arg(args,type);
// 释放va_list变量
va_end(args);
下面给出一个例子:
int add_nums(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()
{
cout << add_nums(4, 25, 25, 50, 50) << endl;
return 0;
}
编译器是将参数压入栈中进行传递的。传递实参的时候,编译器会从实参列表中,按从右到左的顺序将参数入栈,对于add_nums(4, 25, 25, 50, 50)的调用,则入栈的顺序是 50, 50, 25, 25, 4 (注意没有可变参数与不可变参数之分)。由于栈的地址是从高到低的,所以在知道了第一个参数地址和参数的类型之后,就可以获取各个参数的地址。
二、可变参数模板










