文章目录
一、可变参数模板
在C语言中其实也有可变参数:
1.1 可变参数的函数模板
C++库里面也有很多使用可变参数函数模板的:
template <class ...Args>
void fun(Args... args)
{
}
Args是一个模板参数包,args是一个函数形参参数包
声明一个参数包Args…args,这个参数包中可以包含0到任意个模板参数
以前只能传递一个对象做参数,有了可变参数包就可以传递0~n个参数:
template <class ...Args>
void fun(Args... args)
{
// 获取参数包中有几个参数
cout << sizeof...(args) << endl;
}
int main()
{
fun();
fun(1);
fun(1, 1.1);
fun(1, 1.1, std::string("abc"));
std::vector<int> v;
fun(1, 1.1, std::string("abc"), v);
return 0;
}
那么怎么把这些参数取出来呢?
1.2 递归函数方式展开参数包
void fun()
{
cout << endl;
}
template <class T, class ...Args>
void fun(T val, Args... args)
{
cout << val << " ";
fun(args...);
}
int main()
{
fun();
fun(1);
fun(1, 1.1);
fun(1, 1.1, std::string("abc"));
return 0;
}
解释:
按照箭头的方式调用,最后当没有参数的时候就会走最上面的函数
1.3 逗号表达式展开参数包
template <class T>
void printArg(T val)
{
cout << val << " ";
}
template <class ...Args>
void fun(Args... args)
{
int arr[] = {
(printArg(args), 0)... };
cout << endl;
}
int main()
{
fun(1, 1.1, std::string("abc"));
return 0;
}
这种展开参数包的方式,不需要通过递归终止函数,printArg不是一个递归终止函数,只是一个处理参数包中每一个参数的函数。
(printArg(args), 0)
:先执行printArg(args)
,再得到逗号表达式的结果0。通过初始化列表来初始化一个变长数组, {(printArg(args), 0)...}
将会展开成((printArg(arg1),0)
,(printArg(arg2),0)
, (printArg(arg3),0), etc... )
,最终会创建一个元素值都为0的数组。在创建数组的过程中会先执行逗号表达式前面的部分printArg(args)
打印出参数,也就是说在构造int数组的过程中就将参数包展开了,这个数组的目的纯粹是为了在数组构造的过程展开参数包。
1.4 empalce相关接口函数
比较:
insert
:
emplace
:
emplace的使用:
int main()
{
std::list<int> lt;
lt.emplace_back();
lt.emplace_back(1);
lt.emplace_back(2);
for (auto& e : lt)
{
cout << e << " ";
}
cout << '\n';
return 0;
}
而emplace在插入自定义类型数据的时候会有区别:
struct A
{
A(