1.将函数形参声明为C++11中的initializer_list标准库类型
步骤:
- 函数原型中使用实例化initializer_list模板代表可变参数列表
- 使用迭代器访问initializer_list中的参数
- 传入实参写入{}中
#include<iostream>
#include <initializer_list>
using namespace std;
int sum(initializer_list<int> il); //函数原型用int实例化initializer_list作为形参
int sum(initializer_list<int> il) {
int sum = 0;
for (auto p = il.begin(); p != il.end(); p++) //使用迭代器访问参数
sum += *p;
return sum;
}
int main() {
cout << sum({ 1,2,3,4,5,6,7,8,9,10 }) << endl;
system("pause");
return 0;
}
注意:
- C++11标准
- 参数放入{}中传递
- 函数原型initializer_list与普通形参相同,位置与参数类型不限
- 同一个initializer_list中参数具有相同的类型,实质上是容器类模板
2.继承C语言,形参声明为省略符,函数实现时用参数列表宏访问参数
步骤:(使用四个宏va_list、va_start(va_list, arg)、va_arg(va_list, type)、va_end(va_list),在头文件stdarg.h中)
- 函数原型中使用省略号
- 函数定义中创建一个va_list变量
- 初始化va_list变量
- 访问参数列表
- 完成清理工作
#include<iostream>
#include <stdarg.h>
using namespace std;
int sum(int count, ...);
int sum(int count, ...) { //count 表示可变参数个数
va_list ap; //声明一个va_list变量
va_start(ap, count); //初始化,第二个参数为最后一个确定的形参
int sum = 0;
for (int i = 0; i < count; i++)
sum += va_arg(ap, int); //读取可变参数,第二个参数为可变参数的类型
va_end(ap); //清理工作
return sum;
}
int main() {
cout <<sum(5,1,2,3,4,5)<< endl;
system("pause");
return 0;
}
注意:
- 省略号必须在参数列表的末尾
- 运行时确定可变参数类型与个数,个数:实参确定,类型:既有约定
- **va_end()**清理内存
- 只能实现顺序访问
- 极不安全:不检查实参数量
3.C++泛型,可变参数模板实现
模板参数包:零个或多个类型参数的集合
函数参数包:零个或多个非类型参数的集合(除浮点数、字符串和类对象,编译期确认结果)
步骤:
- 编写含有模板参数包和函数参数包的模板参数
- 函数定义递归调用自己,每一步递归参数包中参数减一
- 编写处理边界情况的模板
#include<iostream>
#include <stdarg.h>
using namespace std;
//用来终止递归并答应最后一个元素的函数
//此函数必须在可变参数版本的print定义之前声明
template <typename T>
std::ostream &print(std::ostream &os, const T &t) {
return os << t; //包中最后一个元素
}
//包中除最后一个元素之外的其他元素都会调用这个版本的pirnt
template <typename T, typename... Args>
std::ostream &print(std::ostream &os, const T &t, const Args &... rest) {
os << t << ","; //打印第一个实参,包中元素减一
return print(os, rest...); //递归调用,打印剩余实参
}
int main() {
print(std::cout,1,'A',"lzw",415,true);
system("pause");
return 0;
}
注意:
- 首先处理边界情况
- 参数包在列表最右侧,从左至右展开
- 模板实现函数重载,编译器根据参数类型自动生成
三种方法比较
- 若非必要,不使用可变参数函数
- 尽量不用可变参数宏,安全性差
- initializer_list最为简单实用
- 可变参数模板支持不同类型参数,但实例过多会使得代码体积增大,递归影响效率
最后给大家推荐一个LinuxC/C++高级架构系统教程的学习资源与课程,可以帮助你有方向、更细致地学习C/C++后端开发,具体内容请见 https://xxetb.xetslk.com/s/1o04uB 链接: link