C++ - unordered_map 运算符 [],意外行为

Jho*_*nRM 2 c++ loops unordered-map

这是我正在处理的一个简单脚本,但我无法理解它为什么会出现意外行为。

基本上,我有一个带有重复的整数数组,我想将元素在数组中出现的次数以及元素的值存储在 unordered_map 中,

然后,对于映射 { k , v }中的每个条目,我需要确定数组中是否存在k + 1,如果存在,则对其进行处理。你可以在下面看到代码。

vector<int> A = {1, 1, 3, 2, 5, 3};

for (int i = 0; i < A.size(); ++i) m[A[i]]++;

int ans = 0;

for (const auto& e: m) {
    if (m[e.first + 1] > 0) ans = max(ans, e.second + m[e.first + 1]);
}
Run Code Online (Sandbox Code Playgroud)

一切似乎都奏效了。但是,当unordered_map 中不存在k + 1时,循环就会终止,我不明白为什么。

根据 c++ 文档,运算符 [] 插入一个新元素,如果它不存在。但这并没有告诉我任何关于循环不起作用的信息。

我怀疑这与我正在修改循环内的 unordered_map 的事实有关。如果是这种情况,你们能详细说明一下吗?

我真的很感谢你的帮助。

Rem*_*eau 6

m[e.first + 1]在循环内部使用会插入一个新元素,m如果它不存在,这会导致循环本身出现问题,因为基于范围的for循环在内部使用迭代器,并且std::unordered_map在使用迭代器迭代时改变它是未定义的行为,如插入可能会使迭代器无效

如果发生插入并导致容器重新散列,则所有迭代器都将失效。否则迭代器不受影响。引用不会失效。仅当新的元素数大于 时才会发生重新散列max_load_factor()*bucket_count()

为避免这种情况,请改用 map 的find()方法来检查键是否存在而不插入它:

for (const auto& e: m) {
    auto iter = m.find(e.first + 1);
    if (iter != m.end()) ans = max(ans, e.second + iter->second);
}
Run Code Online (Sandbox Code Playgroud)