boost :: unordered_map.emplace(Args&& ... args)如何工作?

时间:2011-01-29 14:57:24

标签: c++ boost unordered-map

根据documentation

  

插入一个用。构造的对象   参数args,在容器中   当且仅当没有元素时   具有等效密钥的容器。

但是可以插入到unordered_map中的唯一对象具有类型std::pair<Key const, Mapped>(因为要插入的对象需要键和值),已知该构造函数具有两个参数。那么为什么它使用可变函数形式呢?当然,我完全不了解这一点。

2 个答案:

答案 0 :(得分:8)

请参阅this有关emplace_back与push_back的文章。本质上,它允许从传递给它的参数构造对象,而无需首先创建要传递的对象。它通过删除通常由于创建要插入的对象而发生的复制结构来节省开销。

所以你可以逃脱这个:

unordered_map<int,int> foo;
foo.emplace(4, 5);

而不是

foo.insert(std::make_pair(4, 5));

更好的,(如果我没记错的话),你可以通过这条路线:

struct Bar{
    int x,y;
    Bar(int _x, int _y) : x(_x), y(_y){}
};

unordered_map<int,Bar> baz;
baz.emplace(4, 5, 6);

取自C++0x上的Wiki:

  

由于rvalue引用的措辞的性质,以及对左值引用(常规引用)的措辞的一些修改,rvalue引用允许开发人员提供完美的函数转发。当与可变参数模板结合使用时,此功能允许功能模板可以完美地将参数转发给另一个采用这些特定参数的函数。这对于转发构造函数参数,创建工厂函数非常有用,它将自动为这些特定参数调用正确的构造函数。

以下列方式工作:

template<typename TypeToConstruct> struct SharedPtrAllocator {

    template<typename ...Args> std::shared_ptr<TypeToConstruct> construct_with_shared_ptr(Args&&... params) {
        return std::shared_ptr<TypeToConstruct>(new TypeToConstruct(std::forward<Args>(params)...));
    }
}

再次,从上面提到的维基文章中无耻地被盗。

答案 1 :(得分:5)

现在C ++标准库集成了Boost的那部分:

来自http://en.cppreference.com

#include <iostream>
#include <utility>
#include <tuple>

#include <unordered_map>

int main(){
    std::unordered_map<std::string, std::string> m;

    // uses pair's piecewise constructor
    m.emplace(std::piecewise_construct,
        std::forward_as_tuple("c"),
        std::forward_as_tuple(10, 'c'));

    for (const auto &p : m) {
        std::cout << p.first << " => " << p.second << '\n';
    }
}

std::piecewise_construct 是一个常量,不会对如何使用参数产生歧义

  • 第一个元组将用于构建密钥
  • 第二个构建值