从std :: vector中删除时出现分段错误

时间:2014-05-22 07:01:25

标签: c++ vector struct segmentation-fault

我正在尝试删除struct的向量中的重复,这个重复由结构中的qieid确定:

struct infotable
{
  int qieid;
  int fid;
  int valid;
};

我写了一个子功能来执行此操作:

void erase_duplicate(vector<infotable> &info)
{
  vector<infotable>::iterator it0,it1;

  for(it0 = info.begin();it0 != info.end()-1; it0++)
  {
    //it1 = find(qieidarray1.begin(),it0,*it0);

    for(it1 = it0 +1;it1 != info.end(); it1++)
    {
      if((*it1).qieid == (*it0).qieid)
        it1 = info.erase(it1);
    }
  }
}

但是我对这段代码有些问题。 当向量中的结构数量很小时,它可以正常工作。但是当我在向量中有超过3000个结构时,程序将出错并且我有:

  

分段错误11

显示在我的屏幕上。 我知道这是一个内存访问问题,我可能会访问我不应该触摸的地方,因为我在向量中有这么多元素。 但是,无论如何我可以改进我的代码以获得更好的性能(运行更多元素)?

3 个答案:

答案 0 :(得分:4)

使用erase时,它将使迭代器无效。

for(it1 = it0 +1;it1 != info.end(); )
{
   if((*it1).qieid == (*it0).qieid)
      it1 = info.erase(it1);
   else
      it1++;
}

答案 1 :(得分:4)

您还可以使用<algorithm>函数来执行此操作,尤其是std::unique

首先,按qieid排序,然后使用unique,它会在末尾移动“已删除”元素并返回一个新的迭代器,然后您可以使用它来实际删除这些元素。

std::sort(info.begin(), info.end(), [](const infotable& a, const infotable& b) {
    return a.qieid < b.qieid;
});
auto newIt = std::unique(info.begin(), info.end(), [](const infotable& a, const infotable& b) {
    return a.qieid == b.qieid;
});
info.erase(newIt, info.end());

这将在O(n + log n)中运行,而您的原始解决方案具有O(n 2 )时间复杂度。就个人而言,我更喜欢这个解决方案,特别是因为它更具表现力,所以更容易看到代码在做什么。

注意:如果您的编译器已经支持C ++ 14的通用lambdas,则可以使用以下命令简化表达式:[](const auto& a, const auto& b) { ... }

答案 2 :(得分:2)

您可以使用std::set技巧删除重复项, 它非常易读,易于维护,但效率较低。

std::vector<int> r = {14,26,58,56,26,14};

std::set<int> s(r.begin(),r.end());
r = std::vector<int>(s.begin(),s.end());

你需要给std :: set你自己的比较函数,以便它能与你的结构一起使用。