在C++98标准中, 我们向vector或者map等常用容器中插入新的元素时,只能使用push_back和insert, 这两个函数不可避免的调用了复制构造函数,导致不必要的复制行为发生.在C++11以及之后的标准中,插入元素这一行为多了一个选项,那就是 emplace.
那么, 他和push_back以及insert 的区别是什么呢? 顾名思义, emplace的字面意思是从内部构造, 如果我们写过模板函数,给出一个类型T,我们可以自己去构造一个T而不是要求外部传入T的实例, 考虑到以下代码
|
|
push_back 是要求给一个Foo的实例,然后进行插入, 而emplace_back 只需要给出类型的构造实参即可, emplace_back通过完美转发的方式, 直接把实参转发给容器元素的类型,然后在内部构造一个新的元素实例,这样就避免了拷贝.
以上是vector容器的用法,那么map容器有两个类型, TKey和TValue, emplace的参数如何传递呢?
|
|
从语法上来说, map的emplace传参要解决的问题就是,如何区分TKey的构造实参和TValue的构造实参, map通过std::piecewise_construct和 tuple完美解决了这一问题, tuple可以容纳任意类型任意个数的参数, 在函数收到一个tuple时,也可以通过一些方法进行unpack, 所以不难想象, emplace内部是把第二个和第三个实参进行unpack后forward到TKey的构造函数和TValue的构造函数.
有了emplace后, 基本上就不会再用push_back和insert了,emplace完全可以做到同样的事情,但是性能会提升很多.