C++空映射赋值:等于vs插入

C++ empty map assignment: equals vs insert

本文关键字:等于 vs 插入 赋值 映射 C++      更新时间:2023-10-16

我有一个朋友在工作,他鼓励我永远不要将键/值对分配到空映射中,如下所示:

int somefunc(map<int, int> somemap) {
    somemap.clear();
    somemap[12] = 42;
}

他说,由于somemap映射变量被清除,因此somemap[12]是一个无效的访问。我推断,任何C++编译器,即使在调试模式下编译,也不会产生不必要地试图访问上面赋值中的somemap[12]的程序集。通常情况下,上面的最后一行将被编译为与此行相同的程序集:

somemap.insert(std::对(12,42));

这是真的吗?与之前的方法相比,有什么理由通过插入进行分配吗?我喜欢早一点的,因为它更短。

是的,如果元素不存在,最后一行将始终插入元素。

来自C++标准第23.4.4.3节:

T& operator[](const key_type& x);
  1. 效果:如果贴图中没有等效于x的关键帧,则将value_type(x,T())插入到贴图中

映射::[]运算符定义为:

返回对映射到与键等效的键的值的引用,如果该键不存在,则执行插入。

std::map重写[]运算符,以便在不存在的键上调用.insert。这里没有问题。

[]它是重载运算符,所以为它编码

    operator[](const key_type& __k)
    {
       // concept requirements
     __glibcxx_function_requires(_DefaultConstructibleConcept<mapped_type>)
      iterator __i = lower_bound(__k);
     // __i->first is greater than or equivalent to __k.
      if (__i == end() || key_comp()(__k, (*__i).first))
           __i = insert(__i, value_type(__k, mapped_type()));
      return (*__i).second;
   }

从这里你可以看到,如果它是空的,它将被插入

映射的operator[]执行以下操作:

  • find元素(键)。如果找到,则返回对它的引用(值&)
  • 如果找不到,请创建一个空元素pair<key,value(default value)>并返回对该值的引用

运算符[]的问题不同。有些人想用它来搜索元素是否存在。这是错误的,因为地图会充满空元素。搜索人员应使用map.find()

最好的方法是测量。但是,库将定位键的位置,如果不存在,则添加一个带有键和默认构造值的新节点。然后,它返回一个进行赋值的引用:库看不到赋值,也就是说,它可以而不能执行的道德等效操作

map.insert(std::make_pair(12, 42));

如果编译器能够检测到它可以执行此操作,我会感到惊讶。对于int来说,差异其实并不重要。对于其他类型,这也不重要,即它们应该有一个有效的默认构造函数。

这两种用法都是有效的,但含义略有不同:

somemap[12] = 42;

将替换somemap[12]的现有值(如果存在),或插入一个新值(如果不存在)。

auto returnValue = somemap.insert<std::make_pair(12, 42));

将为somemap[12]插入一个新值(如果还不存在),或者如果已经有12的映射,则保持该值不变。你可以判断它是否像这样工作:

if(returnValue.second)
{
   // it worked.  
   // returnValue.first is an iterator pointing to the newly added element
}
else
{
    // it failed.
    // returnvalue.first is an iterator pointing to the unchanged pre-existing element.
}