所以我的无序地图是从字符串到双重
的映射unordered_map<string,double> u_map;
unordered_map<string,double> other_u_map;
我这样迭代
for (auto it : u_map){
if(isTrue){
other_u_map[it.first] = returnsDouble(); //Segfaults here
u_map.erase(it.first);
}
}
对于一些测试用例,它运行完美而没有segfaulting。然后其他时候它会在这一行之后发生段错误,这没有任何意义,因为我所做的就是为它指定一个双键。如果密钥不存在,那么它应该创建一个。由于我使用的是C ++数据类型(字符串和双精度型),所以创建我自己的数据结构不会导致段错误或访问mem越界,就像我在其他SO问题中看到的那样。这可能是使用
的问题for (auto it : u_map)
或者这可能是在这一行之前发生的问题
等我忘了添加我擦除u_map中的键是问题吗?
答案 0 :(得分:5)
不幸的是,你不能在这里使用基于范围的for循环,你必须明确地使用迭代器。
for (auto it = std::begin(u_map); it != std::end(u_map); ) {
// ^ no it++ here
if (isTrue) {
other_u_map[it->first] = returnsDouble();
// ^ changed to -> because it is now iterator
it = u_map.erase(it);
} else {
++it;
}
}
C ++代码中最常见的一个错误是使用无效的迭代器。当您的集合更新时,迭代器不会更新。请记住,问题中基于for循环的范围等同于:
for (auto pos = std::start(u_map), end = std::start(u_map);
pos != end; ++pos) {
auto it = *pos;
...
}
问题是.erase()
使pos
无效,因此之后调用++pos
是违法的。
答案 1 :(得分:1)
等我忘了添加我擦除u_map中的键是问题吗?
是。 Range-based for loop做同样的事情:
{
auto && __range = range_expression ;
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
这意味着元素在循环内被擦除的事实将导致访问不存在的元素(即,超出当前范围unordered_map
);这是UB。