What is the difference between std::unordered_map::emplace
and std::unordered_map::insert
in C++?

- 9,137
- 11
- 75
- 83

- 613
- 1
- 6
- 6
-
3Taken from a [reference](http://en.cppreference.com/w/cpp/container/unordered_map/emplace): *Careful use of emplace allows the new element to be constructed while avoiding unnecessary copy or move operations. The constructor of the new element (i.e. `std::pair
`) is called with exactly the same arguments as supplied to emplace, forwarded via `std::forward – chris Oct 19 '14 at 01:33(args)...`.* -
emplace creates a new object whereas insert takes an existing object. The parameters are different as emplace takes the constructor arguments. If you don't have an instance already existing to insert, use emplace. – Neil Kirk Oct 19 '14 at 01:34
2 Answers
unordered_map::insert
copies or moves a key-value pair into the container. It is overloaded to accept reference-to-const or an rvalue reference:
std::pair<iterator,bool> insert(const std::pair<const Key, T>& value);
template<class P>
std::pair<iterator,bool> insert(P&& value);
unordered_map::emplace
allows you to avoid unnecessary copies or moves by constructing the element in place. It uses perfect forwarding and a variadic template to forward arguments to the constructor of the key-value pair:
template<class... Args>
std::pair<iterator,bool> emplace(Args&&... args);
But there is a great deal of overlap between the two functions. emplace
can be used to forward to the copy/move constructor of the key-value pair which allows it to be used just as insert
would. This means that use of emplace
doesn't guarantee you will avoid copies or moves. Also the version of insert
that takes an rvalue-reference is actually templated and accepts any type P
such that the key-value pair is constructible from P
.
In principle, emplacement functions should sometimes be more efficient than their insertion counterparts, and they should never be less efficient.
( Edit: Howard Hinnant ran some experiments that showed sometimes insert
is faster than emplace
)
If you definitely do want to copy/move into the container it might be wise to use insert
because you are more likely to get a compilation error if you pass incorrect arguments. You need to be more careful you are passing the correct arguments to the emplacement functions.
Most implementations of unordered_map::emplace
will cause memory to be dynamically allocated for the new pair even if the map contains an item with that key already and the emplace
will fail. This means that if there is a good chance that an emplace
will fail you may get better performance using insert to avoid unneccessary dynamic memory allocations.
Small example:
#include <unordered_map>
#include <iostream>
int main() {
auto employee1 = std::pair<int, std::string>{1, "John Smith"};
auto employees = std::unordered_map<int, std::string>{};
employees.insert(employee1); // copy insertion
employees.insert(std::make_pair(2, "Mary Jones")); // move insertion
employees.emplace(3, "James Brown"); // construct in-place
for (const auto& employee : employees)
std::cout << employee.first << ": " << employee.second << "\n";
}
Edit2: On request. It is also possible to use unordered_map::emplace
with a key or value that takes more than one constructor parameter. Using the std::pair
piecewise constructor you can still avoid unnecessary copies or moves.
#include <unordered_map>
#include <iostream>
struct Employee {
std::string firstname;
std::string lastname;
Employee(const std::string& firstname, const std::string& lastname)
: firstname(firstname), lastname(lastname){}
};
int main() {
auto employees = std::unordered_map<int, Employee>{};
auto employee1 = std::pair<int, Employee>{1, Employee{"John", "Smith"}};
employees.insert(employee1); // copy insertion
employees.insert(std::make_pair(2, Employee{"Mary", "Jones"})); // move insertion
employees.emplace(3, Employee("Sam", "Thomas")); // emplace with pre-constructed Employee
employees.emplace(std::piecewise_construct,
std::forward_as_tuple(4),
std::forward_as_tuple("James", "Brown")); // construct in-place
}

- 14,926
- 3
- 34
- 54
-
*"Emplacement functions are often more efficient than their insertion counterparts, and they’re never less efficient."* Howard Hinnant measured something different: http://htmlpreview.github.io/?https://github.com/HowardHinnant/papers/blob/master/insert_vs_emplace.html See also: https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-discussion/emplace/std-discussion/YQ4BGAvxIhw/jTfn1RIm9IkJ – dyp Oct 19 '14 at 04:16
-
@Yakk Ah, I'm sorry. Hope this works: https://groups.google.com/a/isocpp.org/d/topic/std-discussion/YQ4BGAvxIhw/discussion `emplace` for associative containers typically creates the element (not just the key) from the arguments even if it's not inserted. So if you already have an element (outside the associative container) and want to copy it, `insert` might be more efficient. – dyp Oct 19 '14 at 12:47
-
@dyp neat. So for efficiency, we need a partial `pair` construct & type, which we can complete in a second pass. And ditto for `tuple`s probably. – Yakk - Adam Nevraumont Oct 19 '14 at 13:05
-
1Alas, no one ever shows an example of a map
where the constructors for T1 and T2 take more than a single argument. I often use things like map – jzions Apr 30 '15 at 21:00. -
"Emplacement functions are often more efficient than their insertion counterparts, and they’re never less efficient." Do you have any citation for that (which is not obsolete)? In fact, at Meeting C++ 2014, Scott Meyers explained that this surprising behavior is the main reason the chapter of the book is entitled "Consider emplacement instead of insertion" instead of "Prefer emplacement …". – Arne Vogel May 18 '15 at 11:27
-
1@ArneVogel I've updated the quote to match what is in the print version of _Effective Modern C++_ (Item 42 page 301). I think the other reason it is "Consider" and not "Prefer" is when you use an emplacement function you have to be careful to make sure you're passing the correct arguments because emplacement functions may perform conversions that would be rejected by insertion functions. – Chris Drew May 18 '15 at 11:58
-
2@jzions I've added an example with a `T2` that is constructed with more than a single argument. – Chris Drew May 31 '16 at 14:25
The difference between emplace()
and insert()
has already been well explained in Chris Drew's answer. However, for the sake of completeness I'd like to add that since C++17 std::unordered_map
provides two new insertion methods: try_emplace()
and insert_or_assign()
. Let me summarize these methods briefly:
try_emplace()
is an "improved" version ofemplace()
. In contrast toemplace()
,try_emplace()
doesn't modify its arguments (due to move operations) if insertion fails due to a key already existing in theunordered_map
.insert_or_assign()
is an "improved" version ofoperator[]
. In contrast tooperator[]
,insert_or_assign()
doesn't require the value type of theunordered_map
to be default constructible.
I have written a more detailed answer on the above mentioned new insertion methods for std::map
here. That answer also applies to std::unordered_map
.

- 9,137
- 11
- 75
- 83