【问题标题】:Does vector::erase() change positions?vector::erase() 会改变位置吗?
【发布时间】:2012-09-04 19:17:59
【问题描述】:

这是我的问题,我有一个 double 向量,我需要在特定条件下消除其中的一些。这是一个代码示例:

 vector <double> appo;
 for(int i=0;i<appo.size();i++){
       for(int j=i+1;j<appo.size();j++){
         if( condition(appo[i],appo[j]) ){
           appo.erase(appo.begin()+j);
           j--;
         }
       }
    }

因为在 erase() 之后,我的大小减 1 并且所有元素都左移了,所以减小 j 是否正确?

好的,我决定不使用 removeif,因为它是一个小程序,我现在不关心性能,但我遇到了分段错误。 代码如下:

vector <double> *point;
for(int i=0;i<point->size();i+=3){
     for(int j=i+3;j<point->size();j+=3){
       if(distance((*point)[i],(*point)[i+1],(*point)[i+2],(*point)[j],(*point)[j+1],(*point)[j+2]) < treshold){
         point->erase(point->begin()+j,point->begin()+j*3);
         j-=3;
       }
     }
  }

point 是一个坐标向量,类似于 (x1,y1,z1,x2,y2,z3,...,xn,yn,zn)。 有什么想法吗?

【问题讨论】:

  • 所有元素删除后的元素std::remove_if 可能会更有效,这取决于很多事情。

标签: c++ vector erase


【解决方案1】:

减少j是正确的,因为在擦除索引j处的元素后,之前在j+1处的元素现在在j处,所以你想再次重复循环j 的值。减少它会产生这种效果,因为循环本身会增加它。

您也可以考虑使用迭代器而不是索引:

vector<double>::iterator j = appo.begin() + i + 1;
while (j != appo.end()) {
    if (condition(appo[i], *j)) {
        j = appo.erase(j);
    } else {
        ++j;
    }
}

完成此操作后,您也可以为 i 使用迭代器。

正如“eq-”在评论中所说,有一个标准算法可以帮助您。就可用性而言,您是否更喜欢循环,但它通常更有效,因为重复调用“擦除”一次将每个元素打乱,而remove_if 跟踪“读取位置”和“写位置”,所以它最多只复制每个元素一次。

appo.erase(
    appo.remove_if(
        appo.begin() + i + 1,
        appo.end(),
        ShouldRemove(appo[i])
    ),
    appo.end()
);

在 C++03 中,您必须定义 ShouldRemove,类似于:

struct ShouldRemove {
    double lhs;
    ShouldRemove(double d) : lhs(d) {}
    bool operator()(double rhs) {
        return condition(lhs, rhs);
    }
};

在 C++11 中,您可以使用 lambda 代替 ShouldRemove:

appo.erase(
    appo.remove_if(
        appo.begin() + i + 1,
        appo.end(),
        [&](double d) { return condition(appo[i], d); }
    ),
    appo.end()
);

您还可以使用std::bind1stboost::bind(在C++03 中)或std::bind(在C++11 中)使用一些选项,但这些选项很难正确理解。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-14
    • 1970-01-01
    • 1970-01-01
    • 2011-09-15
    • 2023-03-26
    • 2011-02-10
    • 2015-03-24
    相关资源
    最近更新 更多