C++ 将[]索引到无序映射时出现SEGFULT
所以我的无序映射是从字符串到双精度的映射C++ 将[]索引到无序映射时出现SEGFULT,c++,C++,所以我的无序映射是从字符串到双精度的映射 unordered_map<string,double> u_map; unordered_map<string,double> other_u_map; 在一些测试用例中,它可以完美地运行,而不会出现故障。然后其他时候它会在这一行之后出现故障,这是没有意义的,因为我所做的只是给键it分配一个double。如果密钥不存在,那么它应该创建一个。由于我使用C++数据类型(字符串和double),创建自己的数据结构并不是导致问题的问题
unordered_map<string,double> u_map;
unordered_map<string,double> other_u_map;
在一些测试用例中,它可以完美地运行,而不会出现故障。然后其他时候它会在这一行之后出现故障,这是没有意义的,因为我所做的只是给键it分配一个double。如果密钥不存在,那么它应该创建一个。由于我使用C++数据类型(字符串和double),创建自己的数据结构并不是导致问题的问题,这是我在其他问题中看到的,导致了分段错误或访问MEM。这可能是因为使用
for (auto it : u_map)
或者这是一个发生在这条线之前的问题
等等,我忘了添加我擦除u_映射中的键,这就是问题所在吗?不幸的是,这里不能使用基于范围的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
是非法的
等等,我忘了加上我在u_地图上擦除了键,这是问题吗
对。做与以下相同的事情:
{
auto && __range = range_expression ;
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
这意味着在循环中删除元素的事实将导致访问不存在的元素(即,超出当前范围的
无序映射
);这是UB。您是否尝试过使用您的范围内的参考?同时尝试分配给it.second
。是的,很抱歉,我忘了添加我在每次迭代中擦除键,我尝试添加对迭代器的引用,但这并不能阻止segfaults。您是否尝试在失败点进行调试?u\u map.erase(it.first)
最肯定的是使它派生自的迭代器无效。@Mac:那不起作用,因为它不是迭代器,它是映射的一个元素(类型为std::pair
)。
{
auto && __range = range_expression ;
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}