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 
    } 
}