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

Posted

技术标签:

【中文标题】C++ - unordered_map 运算符 [],意外行为【英文标题】:C++ - unordered_map operator [], unexpected behavior 【发布时间】:2020-04-01 00:27:39 【问题描述】:

这是我正在编写的一个简单脚本,但我不明白为什么它的行为异常。

基本上,我有一个带有重复的整数数组,我想将元素在数组中出现的次数连同元素的值一起存储在 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]);

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

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

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

非常感谢您的帮助。

【问题讨论】:

【参考方案1】:

在循环中使用m[e.first + 1] 将在m 中插入一个新元素(如果它不存在),这将导致循环本身出现问题,因为range-based for loop 在内部使用迭代器,并在您更改std::unordered_map 时使用迭代器进行迭代是未定义的行为,如an insertion may invalidate the iterators:

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

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

for (const auto& e: m) 
    auto iter = m.find(e.first + 1);
    if (iter != m.end()) ans = max(ans, e.second + iter->second);

【讨论】:

以上是关于C++ - unordered_map 运算符 [],意外行为的主要内容,如果未能解决你的问题,请参考以下文章

c++ stl unordered_map 如何打印其所有值?

unordered_map 段错误

力扣剑指56:数组中数字出现的次数C++位运算之触类旁通

C++ 如何清空unordered_map

在 C++ 中的重载运算符中使用局部变量

C++ 错误:“unordered_map”未命名类型