1、initializer_list形参
如果函数的实参数量未知但是全部实参的类型都相同,我们可以使用initializer_list类型的形参(C++11新标准)
initializer_list提供的一些操作:
#include<initializer_list> // 头文件
initializer_list lst; // 默认初始化,T类型元素的空列表
initializer_list lst{a,b,c…}; // 初始化为初始值列表的副本
lst2(lst) // 拷贝或赋值不会拷贝列表中的元素;拷贝后,
lst2 = lst // 原始列表和副本共享元素
lst.size() // 列表中的元素数量
lst.begin() // 返回指向lst中首元素的指针
lst.end() // 返回指向lst中尾元素下一位置的指针
测试代码:
#include <iostream>
#include<initializer_list>
using namespace std;
int addSum(initializer_list<int> li)
{
int sum = 0;
for (auto i = li.begin(); i != li.end(); ++i)
{
sum += *i;
}
return sum;
}
int main()
{
int sum = addSum({ 1, 2, 3, 4, 5, 6 }); //需要加{}
cout << sum << endl;
return 0;
}
测试结果:
2、省略符形参va_list
经典的打印函数printf就是用这种方法
int printf(const char* format, …)
用到的几个宏定义
#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);
测试代码:
#include <iostream>
#include<initializer_list>
#include<stdarg.h>
using namespace std;
int addSum(int count,...) //按从右到左的顺序将参数入栈,栈顶是count(表示参数个数)
{
int sum = 0;
va_list args;
va_start(args, count); //args指向栈顶
for (int i = 0; i < count; ++i)
{
sum += va_arg(args, int);
}
return sum;
}
int main()
{
int sum = addSum( 6,1, 2, 3, 4, 5, 6 ); //需要预先设定元素个数
cout << sum << endl;
return 0;
}
3、可变参数模板
典型用法
// Args是一个模板参数包;rest是一个函数参数包
template <typename T, typename...Args>
void foo(const T &t, const Args&...rest);
可变参数函数模板通常是递归的。第一步调用处理包中的第一个实参,然后用剩余的实参调用自身。为了终止递归,我们还需要定义一个非可变参数的函数模板:
测试代码:
#include <iostream>
#include<initializer_list>
#include<stdarg.h>
using namespace std;
//终止递归
template<typename T>
T addSum(T val)
{
return val;
}
template<typename T,typename ... Args>
T addSum(T first,Args... args) //
{
return first+addSum<T>(args...); //递归调用自身,直到没有参数,所以需要设置终止递归特化函数
//1:1+addSum(2,3,4,5,6)
//2:2+addSum(3,4,5,6)
//3:3+addSum(4,5,6)
//4:4+addSum(5,6)
//5:5+addSum(6) //最后一次调用上面的终止递归函数,return后依次递归返回值
}
int main()
{
int sum = addSum(1, 2, 3, 4, 5, 6 ); //
cout << sum << endl;
return 0;
}