【问题标题】:std::map insert && overload causes copystd::map insert && 重载导致复制
【发布时间】:2018-10-28 03:27:33
【问题描述】:

看看这个有趣的演讲:

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

我还在思考为什么会选择&amp;&amp;重载(1)。

  • std::pair&lt;iterator,bool&gt; insert( value_type&amp;&amp; value ); (1)

  • std::pair&lt;iterator,bool&gt; insert( const value_type&amp; value ); (3)

其中value_typestd::pair&lt;const Key, T&gt;

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

【问题讨论】:

  • _const_ 在这种情况下的别名是什么?只是const?
  • @Xirema 我假设它是 OP 试图将 markdown 放入代码块中的别名。如果我错了就恢复。

标签: c++ stl stdmap value-categories


【解决方案1】:
  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

【讨论】:

  • C++17 添加了重载占用value_type&amp;&amp;,我没有看到重载占用value_type&amp;(这是它传递的内容)。
【解决方案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&amp;

【讨论】:

  • 由于什么原因导致采用模板参数的重载?我觉得我错过了一些微不足道的东西,但我什么都没有想到。您介意提供一些资料吗,或者如果答案很简单,请您自己提供?
  • 对不起,我没有理性,后来添加了 value_type&amp;&amp; 的那个(在 C++17 中)。转发引用还很年轻...
  • 为什么转发引用过载会导致制作额外的副本?似乎对原始对象的引用应该传递给 value_type 的构造函数,与 const-reference 重载相同。
  • 第二次重载将使用 emplace 代替,这似乎更慢(您的链接视频也涵盖了)(请记住密钥已经存在,因此创建的节点会立即被销毁,而 insert 可以在创建之前检查存在)。
  • 地图的value_typepair&lt;const Key, Value&gt;,因此您不想强制提前转换为value_type 临时地址,因为这样您就无法从键中移动,因此模板插入.不过,这只是实现部分错过的优化。
猜你喜欢
  • 1970-01-01
  • 2016-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-01
  • 1970-01-01
  • 2013-01-25
相关资源
最近更新 更多