可变模版参数是C++11新引入的机制,其本质是模版的模版,一个可变参数模版支持可变数量参数的函数模版和类模版。和普通模版函数一样,你在函数界面可以传值,也可以传左值引用或者万能引用。其基本语法规则是在定义模版处需要在参数类型前加上三个点,然后再函数中需要在函数类型后加上三个点。注意,引用符号要放在点前类型后。如果使用引用传参,依旧遵循引用折叠的规则。

基本语法及原理

template <class ...Args>
void Print(Args... args)
void Print(Args&... args)
void Print(Args&&... args)

sizeof...(args)//注意,这里的sizeof...是一个整体运算符,算的就是参数包中参数的个数。

可变参数模版的本质还是模版,只不过他的泛化性更强大了,例如以下几次调用的本质是创建一个又一个新的函数

template <class ...Args>
void Print(Args... args)
{
}

int main()
{
    double x = 5.6;
    Print();//0个参数,实例化Print()
    Print(3);//1个参数,实例化Print(int&& arg1)
    Print(1,"wer");//2个参数,实例化Print(int&& arg1,string&& arg2)
    Print("wer",x,9);//3个参数,实例化Print(string&& arg1,double& arg2,int&& arg3)

}

包扩展

对于参数包Args,相比计算参数个数,使用参数才是我们的目的。如下图,这是一种利用递归的方法来获取参数。ShowList模版函数中,args的第一个参数会给到T,剩下的参数重新构成参数包变成递归下一个函数的参数包。

#include <iostream>

using namespace std;

void ShowList()
{
	cout << endl;
}

template <class ...Args,class T>
void  ShowList(T data, Args&&... args)
{
	cout << data<< ' ';
	ShowList(args...);
}

template <class ...Args>
void Print(Args&&... args)
{
	ShowList(args...);
}

int main()
{
	Print(1, 2, 2.2, "how are you");

	return 0;
}

emplace系列

emplace系列的接口会变成模版可变参数,从理论上来说emplace兼容push和insert系列,但是又比push和insert效率要高一点。emplace系列支撑直接插入构造T对象的参数,例如一下代码,emplace_back会直接进行构造,而push还需要套一层{}的壳,然后进行构造。并且push走的是先构造一个临时对象,接着再移动构造出目标对象,整体效率会比emplace系列低那么一点点,因此,在大多数情况下,推介直接诶使用emplace系列。

emplace_back(“zzzz”,2);
push_back({“zzzz”,2});

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐