在迭代时修改set会给我分段错误

时间:2017-12-14 09:33:55

标签: c++ vector segmentation-fault

我目前正在使用 int of int 向量的函数。 我希望我的函数 merge()合并所有共享int的集合,所以例如我想要这样做:

  [0]  -  0, 1, 2                              
  [1]  -  1, 3            Then it will              [0]  -  0, 1, 2, 3
  [2]  -  0, 3            output this vector ->     [1]  -  4, 5
  [3]  -  4, 5                                      [2]  -  6, 7, 8, 9
  [4]  -  6, 7, 8                                   
  [5]  -  8, 9  

我已经写过这个函数,其代码在这里展示。 我几乎对每一行都进行了评论,因此理解我的代码并不太难!

// Merges all sets that shares at least one int
//
// PARAMETERS...
//      vectorE         : vector of sets of int
void mergeStates( std::vector< std::set< int > >& vectorE )
{
    // For every set of ints
    for( auto &currentSet : vectorE )
    {
        // For every ints of the set
        for( auto currentInt : currentSet )
        {   
            // The two for( ) loops down there allow me to iterate over 
            // every int of every set of the vectorE
            for( auto setToCheck : vectorE )
            {
                // If the set is different from the one we're already targeting
                if( currentSet != setToCheck )
                {
                    for( auto intToCheck : setToCheck )
                    {
                        // if we have found an int that is the same as the one we're targeting
                        if( intToCheck == currentInt )
                        {
                            // Merge
                            etatsetEtudie.insert( setToCheck.begin(), setToCheck.end() );

                            // Deleting the set we copied from, because we won't need it anymore
                            for(auto setToErase = vectorE.begin() ; setToErase != vectorE.end() ; ){
                                if( *setToErase == setToCheck )
                                    setToErase = vectorE.erase( setToErase );
                                else
                                    ++setToErase;
                            }
                        }
                    }
                }
            }
        }
    }
}

每次运行我的程序时,在删除我们复制的集合时会出现段错误:我的错误在哪里?

编辑:我开始工作了!

好的,谢谢大家,我只是简单地创建了参数const并添加了一个返回值,这样我就可以动态地将每个构造的集合添加到一个新的向量中,并返回这个向量: - )

4 个答案:

答案 0 :(得分:0)

问题不在于修改任何集合,它正在修改向量。

从矢量中删除某些内容后会移动元素。首先,这意味着在擦除位置(for-range循环内部使用迭代器)后向量中的迭代器不再有效。其次,如果移位复制和覆盖设置(而不是移动它们),那么所有迭代器都将不再有效。

结果是代码中存在大量未定义的行为。

此外,即使方法有效,最内层循环也不是擦除集合的好方法。这非常非常低效。

至少,您需要重新考虑清除元素的方式。但我认为提出一个通常更好的算法将是更好的方法。

答案 1 :(得分:0)

您正在使用无效迭代器的std::vector::erase函数。因此,range based for loop内的代码会尝试通过容器端访问迭代器。

答案 2 :(得分:0)

基于范围的for使用的结束迭代器是在循环之前确定的。由于您在迭代期间erase(),结尾实际上会发生变化。从erase()的结果中获取迭代器是不够的,因为结束也发生了变化。我认为你可以逃避不使用基于范围的for循环来删除你的范围。

答案 3 :(得分:0)

尝试创建一个新的向量而不是修改原始向量:

std::vector<std::set<int>> mergeStates(const std::vector<std::set<int>> & vectorE ) {
    std::vector<std::set<int>> new_vector;

    ...

    return new_vector;
}