简体   繁体   English

从向量C ++中删除多个元素

[英]Removing multiple elements from a vector c++

Here is some code which checks if 2 units are killed after they attack each other, I pass in the position in the vector however when I remove one the vector is changed in size and therefore the 2nd unit is out of range. 这是一些代码,用于检查2个单元在相互攻击后是否被杀死,我通过了向量中的位置,但是当我删除一个单元时,向量的大小已更改,因此第二个单元超出范围。 How can I remove both simultaneously? 如何同时删除两者?

if ((MyHealth <= 0) && (EnemyHealth <= 0))
{
    PlayerUnits.erase(PlayerUnits.begin() + MyUnit, PlayerUnits.begin() + EnemyUnit);
}
else if (MyHealth <= 0)
{
    PlayerUnits.erase(PlayerUnits.begin() + MyUnit);
}
else if (EnemyHealth <= 0)
{
    PlayerUnits.erase(PlayerUnits.begin() + EnemyUnit);
}

Instead of coding the removal logic yourself, it would be better managed using std::remove_if from algorithm . 与其自己编写删除逻辑,不如使用algorithm std::remove_if更好地管理它。 Depending on whether you have compiler supporting C++11 or not, the Predicate can either be a lambda or a named function. 根据您是否具有支持C ++ 11的编译器,谓词可以是lambda或命名函数。

First point: In your first block, the call erase(x, y) does something different than you expect - it erases a whole range of elements starting at index x until just before index y. 第一点:在您的第一个程序段中,调用erase(x, y)所做的事情与您预期的不同-它删除了从索引x开始直到索引y之前的整个元素范围 For example, if we have the vector [a,b,c,d,e,f,g], then erase(2,5) will erase indexes 2,3,4, so we end up with [a,b,f,g]. 例如,如果我们有向量[a,b,c,d,e,f,g],则delete(2,5)将擦除索引2,3,4,因此我们以[a,b, F,G]。 I'm guessing you want to erase just two elements, not an entire range. 我猜您只想删除两个元素,而不是整个范围。

Second point: As Dieter Lücking pointed out, simply erase the higher index element first, like this: 第二点:正如DieterLücking指出的那样,首先只需删除较高索引元素,如下所示:

if (MyUnit > EnemyUnit) {
    PlayerUnits.erase(PlayerUnits.begin() + MyUnit);
    PlayerUnits.erase(PlayerUnits.begin() + EnemyUnit);
} else {
    PlayerUnits.erase(PlayerUnits.begin() + EnemyUnit);
    PlayerUnits.erase(PlayerUnits.begin() + MyUnit);
}

I think a better way to handle this would be to add an "isDead" condition to your "unit" class: 我认为处理此问题的更好方法是在“单元”类中添加“ isDead”条件:

void Unit::Update()
{
    //other stuff
    if(this->m_health <= 0) this->m_isDead = true;
}

then in the main loop: 然后在主循环中:

void Game::Update()
{
   size_t size = PlayerUnits.size();

   //iterate backwards, so there is no skipping
   for(int i = size-1; i>= 0; i--)
   {
       PlayerUnits[i]->Update();
       if(PlayerUnits[i]->isDead()) PlayerUnits.erase(PlayerUnits.begin() + i);
   }
}

This is at least how I personally do it. 至少这是我个人的方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM