[英]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.