在循环中删除向量的一个元素

时间:2016-12-12 20:55:07

标签: c++

for (Shape *i : shapes) {
    for (Shape *j : shapes) {
        if (i != j) {
            if (check(i,j)){
                shapes.erase(remove(shapes.begin(), shapes.end(), i), shapes.end()); 

这会导致错误,因为即使我不存在它也会继续进行迭代,我的问题是如何干净地执行此操作?目前我收到错误"矢量迭代器不可递增"

我可以退出第二个循环并继续第一个循环吗?

3 个答案:

答案 0 :(得分:2)

当你通过范围循环迭代时,你不能从向量中删除元素,因为在内部它使用了无效的迭代器。这应该有效:

auto end = shapes.end();
for( auto it = shapes.begin(); it != end; ++it ) {
    end = shapes.erase( std::remove_if( std::next( it ), shapes.end(), [it]( Shape *s ) { 
             return check( *it, s ); 
         }, shapes.end() );
}

请注意,此代码比您的代码更有效,但它假定为check( s1, s2 ) == check( s2, s1 ),如果您可以更改check()函数以执行严格的排序比较,而不是等效,那么您就可以使用std::sortstd::unique更有效。

答案 1 :(得分:1)

在这种情况下,您不能使用range-for循环。而是使用带迭代器的标准循环:

for(auto iter = shapes.begin(); iter!= shapes.end(); iter ++)

答案 2 :(得分:1)

在使用基于范围的shapes循环时,您无法修改for元素的位置。范围循环在内部使用迭代器,并且擦除vector元素使现有迭代器无效。

尝试更像这样的东西:

auto iter = shapes.begin();
auto end = shapes.end();
while (iter != end) {
    auto iter2 = shapes.begin();
    bool erased = false;
    while (iter2 != end) {
        if ((iter != iter2) && check(*iter, *iter2)) {
            iter = shapes.erase(iter); 
            end = shapes.end(); 
            erased = true;
            break;
        }
        ++iter2;
    }
    if (!erased)
        ++iter;
}

或者,也许更像这样的东西也可以起作用:

shapes.erase(
  std::remove_if(shapes.begin(), shapes.end(),
    [shapes&](Shape *i) {
        for (Shape *j : shapes) {
            if ((i != j) && check(i, j)) {
                return true;
            }
        }
        return false;
    }
  ),
  shapes.end()
);