请考虑以下代码,这会导致访问冲突:
for(std::list<ProjectileNode*>::iterator it = m_Projectiles.begin(); it!=m_Projectiles.end(); it++)
{
if(!(*it)->isActive()) //isActive returns a bool
{
m_Projectiles.remove((*it));
}
}
if(!(*it)->isActive())
导致异常。
我是新手使用列表,可以使用一些帮助。指向对象在其他地方进行管理,因此我不希望它们被销毁,只是从列表中删除,而不会导致此异常
答案 0 :(得分:9)
由于您已经有要从列表中删除的元素的迭代器,因此不应使用remove()
,因为这会再次搜索该元素。相反,使用erase()
,它还返回一个指向擦除元素之后的迭代器。
这导致经典的“擦除一些元素”循环,如下所示:
for(std::list<ProjectileNode*>::iterator it = m_Projectiles.begin(); it != m_Projectiles.end(); /*increment in body*/)
{
if(!(*it)->isActive()) //isActive returns a bool
{
it = m_Projectiles.erase(it);
}
else
{
++it;
}
}
当然,@ juanchopanza的答案显示了如何使用标准算法完全不使用循环。
答案 1 :(得分:7)
您最好的选择是使用std::list::remove_if
和合适的谓词:
bool pred(const ProjectileNode* p) { return !p->isActive(); }
m_Projectiles.remove_if(pred);
或者,在C ++ 11中,
m_Projectiles.remove_if([](const ProjectileNode* p)
{ return !p->isActive(); });
答案 2 :(得分:3)
这是经典的迭代器失效我很害怕。
m_Projectiles.remove((*it));
无效 it
。 it++
循环执行的for
执行将为您提供未定义的行为。那你确实处在一个不好的地方。
原始解决方案是使用
if (!(*it)->isActive()){
std::list<ProjectileNode*>::iterator new_it = it;
++new_it; /*I prefer this to new_it++*/
m_Projectiles.remove((*it));
it = new_it;
} else {
++it;
}
作为if
语句的正文并删除 it++
循环中的for
。重构生产代码。我在这里做的是将迭代器推进到安全节点,然后删除我不再需要的那个。