在闭环矢量擦除功能不擦除类矢量正常(Vector erase function in for loo

2019-10-30 04:00发布

我有一个循环的简单:

for (int i = 0; i < c.numparticles; i++)
{
    if ( labs((noncollision[i].getypos())) > 5000 )
    {
        noncollision.erase (noncollision.begin()+i);
    }
}

其中noncollision是类的一个矢量particle 。 在这个具体的例子中,任何noncollision具有ypos大于5000应被擦除。 我一直与一个noncollision的6大小,其中2 ypos比5000然而,这对循环只擦除其中的一个,完全无视其他大得多。 我怀疑是因为noncollision是类的载体,这个班以某种方式保护,或导致阵列功能,采取不同的行动? 这里是我的声明noncollision ,和particle

vector<particle> noncollision;

class particle{
private:
int xpos;
int ypos;
int xvel;
int yvel;
bool jc; // Has the particle just collided?
public:
etc....
};

任何人都可以解释为什么发生这种情况,以及如何纠正呢? 难道我莫名其妙地需要建立一个“擦除功能”为particle类?

Answer 1:

如果你有两个候选元素彼此相邻(比如,在i=5i=6 ),那么你跳过第二个,因为你只是删除在一个i=5 ......那么第二个变成新的 i=5 ,但你增加i得到i=6上的下一个循环。

你需要修复你的循环正常支持的事实,你同时去除你遍历这同一个容器中的元素。

通常,你会用实际的迭代器(而非计数器i ),以及vector::erase方便地返回一个新的迭代器,为您的下一次迭代:

vector<particle>::iterator it = noncollision.begin(), end = noncollision.end();
for ( ; it != end; ) { // NB. no `++it` here!
    if (labs(it->getypos()) > 5000) {
       // erase this element, and get an iterator to the new next one
       it  = noncollision.erase(it);

       // the end's moved, too!
       end = noncollision.end();
    }
    else {
       // otherwise, and only otherwise, continue iterating as normal
       it++;
    }
}

然而,引述乔Z:

另外,由于erase可以以向量的大小是O(N),则可能的(a)的基准使用反向迭代也(b)考虑复制未擦除的元件到一个新的载体,而不是删除元素圈外的中间,或使用(c)中list<>代替vector<>如果从中间删除是一种常见的操作。


或者,如果你懒,你也只是扭转你的迭代顺序,它保留您的计数器的神圣i在这种特殊情况下:

for (int i = c.numparticles-1; i >= 0; i--) {
    if (labs(noncollision[i].getypos()) > 5000) {
        noncollision.erase(noncollision.begin()+i);
    }
}

只是要小心,从来没有改变i为无符号变量(和你的编译器可能是警告你要做到这一点-即使用size_t而不是-如果c.numparticles有一个合理的类型),因为如果你这样做,你的循环将永远不会结束!



Answer 2:

然而,这对循环只擦除其中的一个,完全忽视了其他。

这是因为你要从前到后。 当你的代码删除在,比如,指数6项,这是以前在指数7项是该指数在6现在。 然而,环路将跳过索引6之后i++ ,以为这样就已经处理了。

如果你去背到前面,这个问题将是固定的:

for (int i = c.numparticles-1; i >= 0; i--)
{
    if ( labs((noncollision[i].getypos())) > 5000 )
    {
        noncollision.erase (noncollision.begin()+i);
    }
}


Answer 3:

它看起来像你从“已失效迭代器”综合症,尽管在这种情况下,它这就是问题的指标。

你接下来要对方抹去的2个元素?

的问题是,擦除从一个向量的元素导致其余底层元素被复制到一个新的位置(除非擦除最后一个元素),和减少一个在矢量元素的数量。

由于您使用的索引到载体中,你不落下的第一个问题(这是被无效迭代器)的犯规,但是:

  • 你只是删除一前一后立即你将永远不会检查元素
  • 你的索引将波及关闭矢量(未定义行为)的结束

修改你在同一回路检查任何序列是一个坏主意。 看一看的remove_if一种更好的方式。 这种算法中把所有匹配的元素在向量的末尾,并返回一个迭代器已移动的第一个,让您安全地删除它们都一气呵成。



文章来源: Vector erase function in for loop is not erasing vector of classes properly