【问题标题】:Difference between two type on insertion in unordered mapunordered_map 中两种插入类型的区别
【发布时间】:2011-07-15 09:52:20
【问题描述】:

首先我使用 make_pair 在我的无序映射中插入键和值。 然后我通过 pmap -x [pid] 检查了我的内存使用情况,它是 535100 Kb

现在我将插入更改为 map[key] = value 现在内存使用量为 535260(增加) 有人可以解释这两个插入的区别。以便我了解内存使用情况。

【问题讨论】:

  • 是什么让你认为这是内存使用差异的原因?您的结果是否可重复?
  • 期望什么?应该没有内存差异吧?
  • 首先,这两个表达式的语义不同。使用产生正确输出的那个,不管它是如何实现的。其次,单个插入的内存使用无法衡量,因此毫无意义。尝试插入 1,000,000 个项目,然后比较内存占用。

标签: c++ stl


【解决方案1】:
map.insert(make_pair(key,value));

使用该键在地图中搜索条目;如果没有,则插入具有给定值的新条目;不会替换此键的现有值。

map[key] = value

使用该键在地图中搜索条目;如果没有,则插入一个具有默认构造值的新条目;然后通过赋值将旧(或新构造的)值替换为新值。

所以第二个版本可能会做更多的工作,如果值类型的默认构造函数这样做的话,可能会临时分配更多的内存。

【讨论】:

  • 如果元素已经存在,为什么还要构造一个临时的?而且,即使它确实发生了,如果它没有发生任何事情,为什么优化器不会忽略它?
  • @Tomalak:如果元素已经存在,则不构造新值;我很确定我没有说会。如果它不存在,则必须默认构造,因为 operator[] 就是这样定义的。如果编译器可以证明复制构造具有相同的效果,则编译器只能省略默认构造和赋值,如果这些操作不平凡,它就不一定能做到。
  • 呃,对不起,我是说元素不存在的情况。可以省略临时构造,因为它会立即与新值交换。 Initialised copies can be elided even if they have side effects. 在这两种情况下,肯定没有持久额外的内存需求。
  • @Tomalak:这不是复制初始化。这是默认构造,后跟赋值,can't be elided。
  • 嗯,我想你是对的。不过,我仍然不明白这与[持续地]消耗更多内存有什么关系。
【解决方案2】:

您无法说出原因。它取决于实现。您使用哪个 STL 编译器?如果可能,请查看来源。

我可以告诉你,例如,以下语句的内存消耗在 VS2010 上是不同的。但这是一个内部优化。(后者使用较少的内存)

shared_ptr<int> i(new int(11));
auto j = make_shared<int>(11));

【讨论】:

    【解决方案3】:

    地图内部存储器的管理由您抽象出来。你不应该关心它,你也不应该关心它。

    无需担心您的特定实现中发生的任何内部问题。

    只需使用提供的 API。如果您坚持调整以实现最佳使用,请配置文件。

    可能性包括:

    • 预分配一块空间
    • 您在测试中犯了一个错误(可能很高兴看到您的测试用例,而不是仅仅听到您抱怨它们......)

    【讨论】:

    • 好的,请告诉我我用过的两种插入方式的区别。
    • 就像你忽略了我刚才所说的一切。
    • 那是一个真正的大声笑! (好的,请告诉我区别......)
    • @Tomalak:就像你忽略了这个问题。微优化可能会浪费时间,比如大约 97% 的时间,但知道如何在需要的时候编写高效的代码并没有什么坏处。
    • @Mike:而且,正如我所说,他可以通过剖析来了解发生了什么。
    猜你喜欢
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 2020-10-04
    • 1970-01-01
    • 2018-07-12
    • 1970-01-01
    • 1970-01-01
    • 2018-11-01
    相关资源
    最近更新 更多