为什么在迭代这个向量时会出现分段错误?

时间:2011-10-01 22:51:54

标签: c++ vector iterator std

我需要浏览此向量并删除重复项。在此代码中的某处发生分段错误。我的猜测是它与迭代器正在进行时删除元素有关,但我真的没有具体理解这些迭代器是如何实际工作的,所以我无法弄明白。

vector<char *>::iterator iter;
for (iter = v->begin(); iter != v->end()-1; iter++ ){
    char *aString = *iter;
    int n = 1;
    while(iter+n != v->end()){
        int comparison = strcmp(aString, *(iter+n));
        if(comparison == 0){
            v->erase(iter + n);
        }
        n++;
    }
}

4 个答案:

答案 0 :(得分:2)

您没有正确地迭代向量的其余部分。 Beta建议的替代方法是使用remove_if进行erase-remove。像这样:

bool compare_strings(char * aString,char * bString)
{
    return 0==strcmp(aString,bString);
}

void remove_duplicates(vector<char *> * v)
{
    vector<char *>::iterator iter;
    for (iter = v->begin(); iter != v->end(); iter++ ) {
        v->erase(std::remove_if(iter+1,v->end(),compare_strings),v->end());
    }
}

答案 1 :(得分:2)

真的,你这里只有一对一的问题。您在删除元素时错误地与end()进行比较并递增n

for (iter = v->begin(); iter != v->end()-1; iter++ ){
                                  ^^^^^^^^

while(iter+n != v->end())
             ^^

以下将做你想要的(并证明它有效):

int main()
{

    std::vector<const char*> v (4, "this");
    std::vector<const char *>::iterator iter;

    for (iter = v.begin(); iter <  v.end(); iter++ ) {
        std::cout << *iter << " ";
    }
    std::cout << std::endl;

    for (iter = v.begin(); iter <  v.end(); iter++ ){
        const char *aString = *iter;
        int n = 1;
        while(iter+n < v.end()){
            int comparison = strcmp(aString, *(iter+n));
            if(comparison == 0){
                v.erase(iter + n);
            }
            else
                n++;
        }
    }

    for (iter = v.begin(); iter <  v.end(); iter++ ) {
        std::cout << *iter << std::endl;
    }

}

输出是:

  

这就是这个这个   此

答案 2 :(得分:1)

从向量中删除元素时,向量会缩短一个元素。试试这个:

if(comparison == 0){
  v->erase(iter + n);
}
else{
  n++;
}

答案 3 :(得分:1)

从向量中删除会使得从erasee开始的所有迭代器无效,所以你可能不应该像你那样构造你的循环,而是使用这样的标准习语:

for (auto it = v.begin(); it != v.end(); ++it)   // no end() - 1 -- may not be legal!
{
  for (auto jt = it; jt != v.end(); )
  {
    if (jt == it) continue;

    if (strcmp(*it, *jt) == 0)
    {
      jt = v.erase(jt);
    }
    else
    {
      ++jt;
    }
  }
}

此代码可以避免检查您的代码无法解释的空向量。