std :: map insert&&过载导致复制

时间:2018-05-17 18:49:19

标签: c++ stl stdmap value-categories

看着这个有趣的话题:

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)。

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

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

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

毕竟,我们没有移动值,所以在我的理解中,表达式p应该是左值而不是x / prvalue,是吗?有人可以启发我吗?

2 个答案:

答案 0 :(得分:2)

你没有采取有问题的重载:

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 :(得分:1)

  1. 调用模板重载(overload (2) on cppreference
  2. 模板重载相当于emplace
  3. emplace并不比insert慢,并且在一般情况下更快,但是......
  4. 但是,emplace允许一次滥用,即当您反复尝试插入相同的密钥时。基准测试就是这样(注意while)。我会说这只是一个基准,当你故意用脚射击自己时会表现出一种行为。在现实世界中,我认为不会通过emplaceinsert来做到这一点。

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

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