我有星形结构列表。这些结构位于std :: list
中我正在对此列表进行双循环并对那些位置进行比较以检测碰撞。当发现A碰撞时,我将删除质量最低的Star。但是当我在双循环中时如何删除Star,并保持循环以检查更多碰撞?
值得一提的是,第二个循环是一个反向循环。
这是一些代码
void UniverseManager::CheckCollisions()
{
std::list<Star>::iterator iStar1;
std::list<Star>::reverse_iterator iStar2;
bool totalbreak = false;
for (iStar1 = mStars.begin(); iStar1 != mStars.end(); iStar1++)
{
for (iStar2 = mStars.rbegin(); iStar2 != mStars.rend(); iStar2++)
{
if (*iStar1 == *iStar2)
break;
Star &star1 = *iStar1;
Star &star2 = *iStar2;
if (CalculateDistance(star1.mLocation, star2.mLocation) < 10)
{
// collision
// get heaviest star
if (star1.mMass > star2.mMass)
{
star1.mMass += star2.mMass;
// I need to delete the star2 and keep looping;
}
else
{
star2.mMass += star1.mMass;
// I need to delete the star1 and keep looping;
}
}
}
}
}
答案 0 :(得分:2)
你需要像这样使用擦除方法的返回值。
iStar1 = mStars.erase(iStar1);
erase = true;
if (iStar1 == mStars.end())
break; //or handle the end condition
//continue to bottom of loop
if (!erase)
iStar1++; //you will need to move the incrementation of the iterator out of the loop declaration, because you need to make it not increment when an element is erased.
如果你没有增加迭代器,如果一个项目被删除并检查你是否删除了最后一个元素那么你应该没事。
答案 1 :(得分:0)
由于修改列表会使迭代器无效(因此无法递增它们),因此必须在更改列表之前保持迭代器的安全。
在大多数实现中,std :: list是一个双链表,因此是一个像
这样的迭代for(auto i=list.begin(), ii; i!=list.end(); i=ii)
{
ii = i; ++ii; //ii now is next-of-i
// do stuff with i
// call list.erasee(i).
// i is now invalid, but ii is already the "next of i"
}
最安全的方法是创建一个包含所有“碰撞”的列表,然后迭代“碰撞”调用list.remove(*iterator_on_collided)
(但效率低,因为O 2 复杂度)
答案 2 :(得分:0)
您希望使用erase()的结果来获取下一个迭代器并以不同方式推进循环:
示例代码看起来像这样:
for (auto oit(s.begin()), end(s.end()); oit != end; )
{
auto iit(s.begin());
while (iit != end)
{
if (need_to_delete_outer)
{
oit = s.erase(oit);
break;
}
else if (need_to_delete_inner)
{
iit = s.erase(iit);
}
else
{
++iit;
}
}
if (iit == end)
{
++oit;
}
}