C++ 函数传递多参数处理 可变参数模板

本文介绍了C++中处理可变参数的三种方法:使用initializer_list处理类型相同的多个参数、利用va_list处理C风格的可变参数、以及采用可变参数模板实现递归调用。通过示例代码展示了每种方法的具体应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值