C ++中的unordered_map :: emplace和unordered_map :: ins有什么区别? [英] What is the difference between unordered_map::emplace and unordered_map::insert in C++?

查看:220
本文介绍了C ++中的unordered_map :: emplace和unordered_map :: ins有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 可用于转发到键/值对的复制/移动构造函数,从而使其可以像插入会。这意味着使用 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.

斯科特·迈耶斯(Scott Meyers)说:


原则上,有时应使用放置功能
比插入的
效率更高,并且它们的效率永远不会比
低。

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 也会导致为新对动态分配内存,并且 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆