在循环列表时,删除列表中的对象的正确方法是什么
What is proper way to delete objects that resides in a list that you find while looping that list?
我有一个Star结构的列表。这些结构位于std::list 中
我正在对这个列表进行双循环,并对那里的位置进行压缩,以检测碰撞。当发现碰撞时,我会删除质量最低的恒星。但当我处于双循环中时,我如何删除恒星,并保持循环以检查更多碰撞?
值得一提的是,第二个循环是一个反向循环。
这是一些代码
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;
}
}
}
}
}
您需要像这样使用擦除方法的返回值。
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.
如果你不增加迭代器,如果一个项目被删除,并检查你是否删除了最后一个元素,那么你应该没事。
由于修改列表会使迭代器无效(因此无法递增),因此在更改列表之前,必须确保迭代器的安全。
在大多数实现中,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)
的"冲突"(但效率低下,因为具有O2复杂性)
您想要使用erase()的结果来获得下一个迭代器并以不同的方式推进循环:
- 如果你使用外部迭代器擦除,你显然可以避免将这个Star与其他Star进行比较,并打破内部循环。只有当内部循环完成时,您才会希望推进外部迭代器,因为否则它将被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;
}
}
相关文章:
- C++ 创建包含链表和字符串的对象的链接列表时出错
- 我使用向量来创建类对象列表.初始化向量时如何使用参数调用构造函数?
- 从封装在对象中的函数 C++ 返回时为空的列表
- 如何在不销毁对象的情况下返回对象列表
- 如何使用Q_PROPERTY公开自定义对象列表
- 链接列表在 cpp 中包含不同的对象类
- 如何使用对象制作分数列表并获得平均值
- 什么更好?返回对象指针列表?或返回指向对象列表的指针?
- 如何将成员函数作为参数传递并在派生对象上执行方法列表
- 我可以从列表中获取对象并复制它们,但如何删除我复制的对象?
- 如何获取列表的每个对象并调用getName方法来打印其名称
- 如何在Windows Media Foundation SDK中指定语言列表对象
- 在 DLL 中嵌入 Python:Py_DECREF列表对象时访问冲突读取位置
- 将类的每个实例添加到列表对象的构造函数
- 列表<对象*>迭代器中的分段错误
- 如何使用list::sort()对STL列表对象进行排序,同时将自定义排序函数作为参数传递给list::排序
- 如何防止客户端修改列表对象
- c++列表对象错误
- 在列表对象中使用对象的派生函数
- 编译器错误 使用列表<对象*的迭代器> C++