std::map 插入 && 过载导致复制

std::map insert && overload causes copy

正在看这个有趣的演讲:

CppCon 2017: Matt Kulukundis “Designing a Fast, Efficient, Cache-friendly Hash Table, Step by Step”

他在大约 38:32 分钟提到

void Benchmark_Slow(int iters) {
    std::unordered_map<string, int> m;
    std::pair<const string, int> p = {};
    while (iters--) m.insert(p)
}

比以下变体慢约 2 倍

void Benchmark_Fast(int iters) {
    std::unordered_map<string, int> m;
    const std::pair<const string, int> p = {};
    while (iters--) m.insert(p)
}

我还在想为什么会选择&&重载(1)。

其中 value_typestd::pair<const Key, T>

毕竟,我们没有移动值,所以在我的理解中,表达式 p 应该是左值而不是 x/prvalue,对吗?谁能赐教一下?

你没有接受有问题的重载:

std::pair<iterator,bool> insert(const value_type& value); // (1)

template< class P >
std::pair<iterator,bool> insert(P&& value); // (2)

P 推导为 value_type&.

  1. 调用了模板重载 (overload (2) on cppreference)
  2. 模板重载相当于emplace
  3. emplace 并不比 insert 慢,而且在一般情况下更快,但是...

但是,emplace 允许一种滥用行为,即您反复尝试插入同一个密钥。基准测试正是这样做的(请注意 while)。我想说的是,当你故意搬起石头砸自己的脚时,这只是一个显示行为的基准。在现实世界中,我不认为有人会通过 emplaceinsert.

来做到这一点

在 C++17 中,这已通过一种需要修改代码的方式得到修复:

  1. try_emplace 函数 https://isocpp.org/files/papers/n4279.html