C++11之emplace
emplace
- 可变参数模版
- emplace系列
- 总结
可变参数模版
C++11⽀持可变参数模板,也就是说支持可变数量参数的函数模板和类模板,可变数⽬的参数被称为参数包,存在两种参数包:模板参数包,表示零或多个模板参数;函数参数包:表示零或多个函数参数。
template <class ...Args> void Func(Args... args) {}
template <class ...Args> void Func(Args&... args) {}
template <class ...Args> void Func(Args&&... args) {}
我们用省略号来指出⼀个模板参数或函数参数的表示⼀个包,在模板参数列表中,class…或typename…指出接下来的参数表示零或多个类型列表;在函数参数列表中,类型名后⾯跟…指出接下来表示零或多个形参对象列表;函数参数包可以用左值引用或右值引用表示,跟前⾯普通模板⼀样,每个参数实例化时遵循引用折叠规则。
可变参数模板的原理跟模板类似,本质还是去实例化对应类型和个数的多个函数。
可以使⽤sizeof…运算符去计算参数包中参数的个数。
在编译时来确定包的参数个数。
emplace系列
emplace系列的接口就是上述的可变参数模版。
先说结论:emplace在插入字面常量的时候要比push_back要高效,因为此时emplace是直接构造,而push_back是构造+移动构造+析构。如果插入的是左值或者右值,效率都一样。
原因就是当插入的是字面常量的时候,emplace是模板函数,而push_back是一个普通函数,因为push_back在类实例化的时候就已经确定了,而emplace是在函数传参的时候才会确定。
那么此时就会进行推演加构造,如果是多个参数就会把参数包给传递下去最后直接在容器里面构造对象。
总结
STL的容器都推荐使用emplace系列,虽然不是每次插入都会比push_back效率高。
但是在传递参数的时候要传对象参数包,例如
list<pair<string,int>>l;
l.emplace_back("1111",2);
l.push_back({"1111",2});
注意两者的区别,对于多参数的类型,如果有{}会识别成initializer_list,这就导致emplace是无法进行识别参数类型的,所以对于多参数类型,emplace是传递的对象参数包。