简体   繁体   中英

unordered_map and emplace, why ctor is called twice?

Here is an example code:

struct T
{
    T(int x) : x_(x)
    {}

    T(T&&) = delete;
    T(const T&) = delete;

    int x_;
};

int main()
{
    std::unordered_map<int, T> m;
    m.emplace(std::piecewise_construct, std::forward_as_tuple(1), std::forward_as_tuple(2));
    m.emplace(std::piecewise_construct, std::forward_as_tuple(1), std::forward_as_tuple(2));

    return 0;
}

Second emplace fails but T constructor is called twice. I have though that emplace will construct an object only when insertion is possible. Could you explain it ?

Edit: I use Visual Studio 2017 compiler.

From cppreference :

The element may be constructed even if there already is an element with the key in the container, in which case the newly constructed element will be destroyed immediately.

The reason for this behavior is that the container needs to construct a key object to be able to check whether it is already present; the mapped object must be constructed at the same time since they are members of the same object (the value_type pair).

try_emplace (since C++17) is a better option in this case, since it will only construct the mapped object if insertion succeeds. It is able to do this since it takes the key as the first argument, and emplaces the mapped object from the remaining arguments, resulting in a far nicer interface:

m.try_emplace(1, 2);
m.try_emplace(1, 2);
              ^ key (copied or moved)
                 ^ mapped_type emplacement args (forwarded)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM