According to the documentation it:

Inserts an object, constructed with the arguments args, in the container if and only if there is no element in the container with an equivalent key.

But the only objects which can be inserted into an unordered_map have type std::pair<Key const, Mapped>(because both a key and a value are needed for an object to be inserted), which is known to take a constructor with exactly two arguments. So why does it use the variadic function form? Surely there is something I am totally not understanding about this.

有帮助吗?

解决方案

See this SO article on emplace_back vs. push_back. Essentially, it allows an object to be constructed from the arguments passed into it without needing to create the object to be passed in first. It saves on overhead by removing a copy construction which normally happens as the result of creating objects to be inserted.

So you can get away with this:

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

instead of

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

Even better, (and if I'm not mistaken), you can go through this route:

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

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

And taken from the Wiki on C++0x:

Due to the nature of the wording of rvalue references, and to some modification to the wording for lvalue references (regular references), rvalue references allow developers to provide perfect function forwarding. When combined with variadic templates, this ability allows for function templates that can perfectly forward arguments to another function that takes those particular arguments. This is most useful for forwarding constructor parameters, to create factory functions that will automatically call the correct constructor for those particular arguments.

Which works in the following manner:

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

Again, shamelessly stolen from the Wiki article mentioned above.

其他提示

Now that the C++ Standard Library has integrated that part of Boost:

From 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 is a constant that leaves no ambiguity about how the arguments will be used

  • The first tuple will be used to construct the key
  • The second to construct the value
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top