>0)个模板参数._c++11 可变参数模板">
赞
踩
( 1 ): C++98/01中,类模板和函数模板只能包含固定数量的模板参数.
( 2 ): 相比于C++98/01,C++11的新特性可变模板参数模板能够让我们创建可以接受可变参数的函数模板和类模板.
以下就是一个基本可变参数的函数模板.
//Args是一个模板参数包,args是一个函数形参参数包.
//声明一个函数形参参数包Args...args,其中这个形参参数包中可以包含0到任意个模板参数.
template < class ...Args >
void ShouList( Args ...args )
{}
注意:
上面的参数args前面有省略号,所以它就是一个可变模板参数,我们将带省略号的参数称为"参数包",它里面包含了0到N个(N>>0)个模板参数.
此外,我们也可以在函数模板内中使用sizeof计算函数形参参数包中参数的个数.
template <class ...Args >
void ShouwList( Args... args)
{
cout << sizeof...( args ) << endl;
}
int main()
{
string str("zh");
ShouwList('A', str); //2
ShouwList(1, 'A', str); //1
}
但是,C++11语法并不支持args[i]这样方式获取可变参数.
//编译无法通过.
template<class ...Args>
void ShowList(Args... args)
{
for (int i = 0; i < sizeof...(args); i++)
{
cout << args[i] << " "; //使用args[i]打印参数包中的每个参数
}
cout << endl;
}
由于我们无法直接获取函数形参参数包args中的每个参数,只能通过展开参数包的方式获取参数包中的每一个参数,这是可变模板参数的一个主要特点,也是最大的难点.但是,我们可以通过一些特殊的办法来获取函数形参参数包的值.
( 1 ) :我们的本意是想通过函数递归的方式,将函数参数包每次调用ShouwList时都分为参数类型T,和参数包(个数-1)的形式,并将此时的函数参数类型T的参数值t打印出来.
( 2 ): 当函数参数包的参数个数为0时,此时与原来的ShouwList函数中的两个形参并不匹配,这时便不能继续递归了.此时,类似与我们以前写递归的结束条件一样,我们需要额外再写一个递归终止函数,随后编译器就会递归调用该函数.
//递归终止函数. void ShouwList ( ) { cout << t << endl; } //利用递归将函数形参参数包展开. template <class T,class ...Args > void ShouwList( T value,Args... args ) { cout << value << " "; ShouwList(args...); } int main() { ShouwList(1); //1 ShouwList(1, 'A'); // 1, A ShouwList(1, 'A', std::string("sort")); // 1, A,sort }
这种展开参数包的方式,不需要通过递归终止函数,而是在expand函数体中展开的.
//将每次的函数形参进行打印. template < class T > void PrintArg(T t) { cout << t << " "; } //利用递归将函数形参参数包展开. template <class ...Args > void ShouwList(Args... args) { int arr[] = { (PrintArg(args),0)... }; cout << endl; } int main() { ShouwList(1); //1 ShouwList(1, 'A'); // 1, A ShouwList(1, 'A', std::string("sort")); // 1, A,sort return 0; }
小结:
可变模板参数一般用于需要传递多个形参的函数.
如果插入实参为int,char等内置类型,那么push_back与emplace_back没有区别.
可是,如果我们存储的数据类型为自定义类型,例如:pair,区别如下.
#include <vector>
int main()
{
vector<pair< std::string,int>> v1;
v1.push_back(make_pair("sort", 1));
v1.emplace_back("sort", 1);
return 0;
}
在vector中,使用emplace_back和push_back传递多个实参调用时没有区别,都是调用一次构造加一次拷贝构造,这种为特殊情况,具体要看vector中的emplace_back的源码.
但是对于STL中其他容器来说,例如:list.在相同情况下,emplace_black相比于push_black来说少调用了一次拷贝构造.
总结:
综合以上情况,我们在插入数据时尽量使用emplace_back,进而更加高效.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。