为什么我得到一个分割错误,而通过这个向量迭代

Why do I get a segmentation fault while iterating through this vector?

本文关键字:迭代 向量 错误 一个 为什么 分割      更新时间:2023-10-16

我需要遍历这个向量并删除重复的。这段代码中的某个地方出现了分段错误。我的猜测是,它与在迭代器运行时删除元素有关,但我对这些迭代器的实际工作原理还没有具体的了解,所以我不能弄清楚。

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

真的,你只是有几个偏离一的问题。当您擦除一个元素时,您正在错误地比较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;
    }
}

输出是:

this this this this this this
这个

没有正确地遍历vector的剩余部分。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());
    }
}

当你从vector中删除一个元素时,vector会缩短一个元素。试试这个:

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

从被擦除的vector对象开始,将使所有迭代器失效,因此您可能不应该像这样构造循环,而应该使用这样的标准习惯用法:

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

这段代码避免了对空向量的检查,因为您的代码没有考虑到这一点。