11

根据文档它:

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

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

4

2 回答 2

8

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

所以你可以摆脱这个:

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 :

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

其工作方式如下:

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)...));
    }
}

再次,无耻地从上面提到的 Wiki 文章中窃取。

于 2011-01-29T15:53:27.583 回答
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是一个常数,不会对参数的使用方式产生歧义

  • 第一个元组将用于构造密钥
  • 第二个构造值
于 2013-09-15T18:04:20.743 回答