7

我看到很多将项目添加到 amapunordered_mapvia 的示例operator[],如下所示:

int main() {
    unordered_map <string, int> m;
    m["foo"] = 42;
    cout << m["foo"] << endl;
}

有什么理由改用insert成员函数吗?看起来他们都做同样的事情。

4

4 回答 4

13

他们不是。

operator[]将覆盖此键的值(如果存在),而不会覆盖insert

如果operator[]用于插入元素,预计会慢一些(有关详细信息,请参阅下面的@MatthieuM 评论),但这在这里并不重要。

虽然std::map::insert返回std::pair< iterator, bool >,其中.second将告诉您该值是已插入还是已存在。


关于您的评论:您不能有 2 个元素具有相同的键和不同的值。这不是一个multimap.

如果地图中有一个元素,与您尝试插入的键相同,则:

  • operator[]将覆盖现有值
  • std::map::insert不会做任何事情。*返回 a std::pair< iterator, bool >.second将在哪里false(说“新元素没有插入,因为这样的键已经存在”)并且.first将指向找到的元素。

*由于@luk32 给出的注释/备注,我改变了这一点;但是写“不会做任何事情”,我并不是字面意思,我的意思是它不会改变现有元素的值

于 2013-04-03T14:02:20.613 回答
3

在某些情况下,使用insert()可以帮助提高性能(更具体地说,std::map因为搜索时间O(log(n))不是恒定摊销的)。举个常见的例子:

std::map<int, int> stuff;

// stuff is populated, possibly large:

auto iterator = stuff.find(27);

if(stuff.end() != iterator)
{
   // subsequent "find", set to 15
   iterator->second = 15;
}
else
{
   // insert with value of 10
   stuff[27] = 10;
}

上面的代码导致两次有效地找到元素。我们可以这样写(稍微)更有效率:

// try to insert 27 -> 10
auto result = stuff.insert(std::make_pair(27, 10));

// already existed
if(false == result.second)
{
   // update to 15, already exists
   result.first->second = 15;
}

上面的代码只尝试一次找到一个元素,降低了算法的复杂性。对于频繁的操作,这可以大大提高性能。

于 2013-04-03T14:28:31.213 回答
2

两者不等价。 insert不会覆盖现有值,并且它返回 a pair<iterator, bool>,其中iterator是键的位置,无论它是否已经存在。bool指示插入是否发生。

operator[]有效地做一个lower_bound关键。如果该操作的结果是iterator具有相同键的 an,则它返回对该值的引用。如果不是,它会插入一个具有默认构造值的新节点,然后返回对该值的引用。这就是为什么operator[]是一个非常量成员 - 如果它不存在,它会自动激活键值。 如果值类型的构建成本很高,这可能会对性能产生影响。

另请注意,在 C++11 中,我们有一个emplace与 几乎相同的方法insert,除了它在发生插入时从转发的参数就地构造键值对。

于 2013-04-03T15:40:41.493 回答
1

好吧,我在一定程度上不同意 Kiril 的回答,我认为它不完整,所以我给出了我的答案。

根据就相当于某个调用。通过这一点,我也认为他说值将被覆盖是错误的。它说:“如果不存在具有键键的元素,则返回对新元素的映射值的引用。否则返回对现有元素的映射值的引用。”cppreference std::map::operator[]insert()

所以它似乎是一个方便的包装器。但是insert(), 具有重载的优点,因此它在一个名称下提供了更多功能。

我向 Kiril 指出一点,乍一看它们似乎确实有一些不同的功能,但是 IHMO 他提供的示例并不相同。

因此,作为使用示例/原因,insert我会指出,一次插入许多元素,或使用hint此处调用 3-6 )。

那么在 map 或 unordered_map 中是否需要 insert()? 我会说是的。此外,operator[]不是必需的,因为它可以使用 来模拟/实现insert,而其他方式是不可能的!它只是提供了更多的功能。但是,写(insert(std::make_pair(key, T())).first)->second)(在cppreference之后)之类的东西似乎比[].

因此,是否有任何理由使用插入成员函数? 我会说重叠功能,地狱不。

于 2013-04-03T14:16:21.290 回答