【问题标题】:Is c++11 operator[] equivalent to emplace on map insertion?c++11 operator[] 是否等同于地图插入时的 emplace?
【发布时间】:2016-08-27 02:03:16
【问题描述】:

对于C++11,以下还有性能差异吗?

(以std::map<Foo, std::vector<Bar> >为例)

map[key] = myVector and map.emplace(key, myVector)

我没有弄清楚的部分是 operator[] 的确切内部。到目前为止,我的理解是(当密钥不存在时):

  1. 在地图内创建一个新键和关联的空默认向量
  2. 返回关联空向量的引用
  3. 将 myVector 分配给引用???

第 3 点是我无法理解的部分,首先如何为引用分配新值?

虽然我无法对第 3 点进行排序,但我认为不知何故只需要复制/移动。假设 C++11 足够聪明,知道这将是一个移动操作,那么整个“[]”赋值是否已经比 insert() 便宜?它几乎等同于 emplace() 吗? ---- 默认构造和移动内容,与直接在原地构造内容的向量?

【问题讨论】:

  • 您的问题是针对map 类型为std::map<Foo, std::vector<Bar>> 还是针对任何类型的地图?
  • 是的,我会更新问题

标签: c++11 dictionary emplace


【解决方案1】:

两者之间有很多差异。

如果您使用operator[],那么map默认构造该值。 operator[] 的返回值将是这个默认构造的对象,然后将使用 operator= 分配给它。

如果你使用emplacemap会直接用你提供的参数构造值。

所以operator[] 方法将始终使用两阶段构造。如果默认构造函数很慢,或者如果复制/移动构造比复制/移动分配快,那么它可能会出现问题。

但是,如果提供的键已经存在,emplace 将不会替换该值。而operator[] 后跟operator= 将始终替换该值,无论那里是否存在。

还有其他区别。如果复制/移动抛出,emplace 保证map 不会被更改。相比之下,operator[] 将始终插入一个默认构造元素。因此,如果后面的复制/移动分配失败,则 map 已经更改。该密钥将与默认构造的 value_type 一起存在。

确实,在决定使用哪一个时,性能并不是您应该考虑的第一件事。您需要首先关注它是否具有所需的行为。

C++17 将provide insert_or_assign,具有map[] = v; 的效果,但有insert/emplace 的异常安全性。

如何首先为引用分配新值?

这与分配给 anyconst 引用基本上没有区别:

int i = 5;
int &j = i;
j = 30;
i == 30; //This is true.

【讨论】:

    猜你喜欢
    • 2013-06-14
    • 2016-06-29
    • 2013-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-18
    相关资源
    最近更新 更多