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

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

问题描述

在C ++中unordered_map :: emplace和unordered_map :: insert之间有什么区别?

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

推荐答案

unordered_map :: insert 复制或将键值对移动到容器中。 重载以接受reference-to-const或右值引用

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 可用于转发到键/值对的复制/移动构造函数,允许使用 insert would。这意味着使用 emplace 不保证您将避免复制或移动。同样,接受rvalue-reference的 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 更快

如果你确实想复制/移动到容器中,使用 insert 可能是明智的,因为你更可能得到一个编译错误if你传递不正确的参数。

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.

小例子:

#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 :: insert之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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