C ++中的unordered_map :: emplace和unordered_map :: ins有什么区别? [英] What is the difference between unordered_map::emplace and unordered_map::insert in C++?
问题描述
std :: unordered_map :: emplace
和 std :: unordered_map :: insert
之间有什么区别C ++?
What is the difference between std::unordered_map::emplace
and std::unordered_map::insert
in C++?
推荐答案
unordered_map :: insert
复制或移动键-值对放入容器中。 它很重,可以接受对常量的引用或右值引用:
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
可以避免通过在适当的位置构建元素来进行不必要的复制或移动。它使用完美的转发和可变参数模板来将参数转发给键值的构造函数对:
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);
但这两个功能之间有很多重叠之处。 emplace
可用于转发到键/值对的复制/移动构造函数,从而使其可以像插入$ c一样使用$ c>会。这意味着使用
emplace
不能保证您会避免复制或移动。同样,带有右值引用的 insert
版本实际上是模板化的,并且可以接受任何类型的 P
,因此键-值对可从 P
构造。
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.
(编辑::Howard Hinnant运行了某些实验显示有时插入
比 emplace
)快
( Howard Hinnant ran some experiments that showed sometimes insert
is faster than emplace
)
如果您确实确实要复制/移动到容器中,则最好使用 insert
,因为您更可能会遇到编译错误如果您传递了不正确的参数。您需要更加小心,将正确的参数传递给放置函数。
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.
unordered_map :: emplace $ c $的大多数实现即使映射中已包含具有该键的项目,c>也会导致为新对动态分配内存,并且
emplace
将失败。这意味着,如果 emplace
很可能失败,则可以使用insert来获得更好的性能,从而避免不必要的动态内存分配。
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.
小例子:
#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 :根据要求。也可以将 unordered_map :: emplace
与具有多个构造函数参数的键或值一起使用。使用 std :: pair
分段构建器,您仍然可以避免不必要的复制或移动。
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
}
这篇关于C ++中的unordered_map :: emplace和unordered_map :: ins有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!