在基于范围的 for 循环中获取无效引用
Getting an invalid reference in a range-based for loop
auto& kphist = this->kphist;
for (auto& it : kphist) {
it.second.aging(); // EXC-BAD-ACCESS
if(it.second.age > LAST_DAY){
kphist.erase(it.first);
continue;
}
}
KPHIST是私人会员
Class A{
private:
unordered_map<int, KeyPointHistory> kphist;
}
调试器显示 kphist 中的所有项目都是有效的,怎么可能在 for 循环中有一个错误的引用。可能出现什么问题?
从 cppreference.com for std::unordered_map::erase()
: 对擦除元素的引用和迭代器无效。其他迭代器和引用不会失效。因此,您不能使用 for 循环范围内的std::unordered_map::erase()
(因为这将尝试递增无效的迭代器)。
为避免递增无效的迭代器,您可以先递增即可然后使用原始迭代器擦除:
for(auto i=map.begin(),end=map.end(); i!=end; ) { // no increment here
auto it=i++; // but here instead
if(must_remove(it))
map.erase(it);
}
事实上,由于erase()
将迭代器返回到下一个元素,因此您可以避免额外的迭代器it
(感谢 Hurkyl 在注释中指出这一点):
for(auto i=map.begin(),end=map.end(); i!=end; ) { // no increment here
if(must_remove(i))
i = map.erase(i); // but here
else
++i; // or here instead
}
无需列出要擦除的元素键...
顺便说一句,你为什么不使用std::map
(而不是std::unordered_map
),因为你的密钥是一个int
(很容易订购)?另外,为什么要对同名的成员变量进行引用kphist
?
在
迭代内容/迭代器时,您不能删除它,也不应该。
将元素索引保存在不同的容器中,完成后循环遍历并擦除您获得的元素。
可能出现什么问题?
万事!
您可以通过直接将迭代器传递给要擦除的项目来擦除unordered_map
。执行此操作时,erase()
返回后续迭代器,因此您可以执行以下操作:
for (auto pos = kphist.begin(); pos != kphist.end(); ) {
it.second.aging();
if(it.second.age > LAST_DAY)
pos = kphist.erase(it);
else
++pos;
}
作为奖励,这可能比传递要擦除的密钥快一点 - 由于您提供了迭代器,因此可以直接到达要擦除的项目,而不是重新散列密钥以找到您已经知道的位置。
相关文章:
- 如何在C++中从两个单独的for循环中添加两个数组
- 为什么我的for循环不能正确获取argv
- 在基于范围的for循环中使用结构化绑定声明
- 通过for循环使用用户输入填充列表
- 使用for循环检查数组中的重复项
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- 正在使用for循环创建QScatterSerie
- Python中的for循环与C++有何不同
- 在更改for循环的第三部分后,未使用for循环结果
- 在 for 循环中查找问题时遇到困难
- 嵌套for循环C++的问题(初学者)
- 如何用for循环在c++中生成单词三角形
- 如何在for循环中包含两个索引值的测试条件
- 带有多个独立参数的C++For循环
- C++ Python 循环"for i, num in enumerate(list):"版本
- C 多循环 for () 基础知识
- 没有条件值的 FOR 循环"for (int i = 1; ; i++)"无法正常工作
- 为用户提供循环for循环的选项
- 打破循环for循环