C++ 从stl列表中删除对象指针
考虑以下导致访问冲突的代码:C++ 从stl列表中删除对象指针,c++,stl,C++,Stl,考虑以下导致访问冲突的代码: 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)); } } for(std::list::iter
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));
}
}
for(std::list::iterator it=m_projectles.begin();it!=m_projectles.end();it++)
{
if(!(*it)->isActive()//isActive返回bool
{
m_射弹。移除((*it));
}
}
如果(!(*it)->isActive())
导致异常
我不熟悉使用列表,需要一些帮助。指向的对象在其他地方进行管理,因此我不希望它们被销毁,只希望从列表中删除,而不会导致此异常恐怕这是典型的迭代器失效
m_射弹。移除((*it))代码>使无效
。由for
循环执行的it++
将为您提供未定义的行为。那你的处境真的很糟糕
一个粗略的解决方案是使用
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)->isActive(){
std::list::iterator new_it=it;
++新的;/*我更喜欢这个而不是新的++*/
m_射弹。移除((*it));
it=新的it;
}否则{
++它;
}
作为if
语句的主体,删除for
循环中的it++
。重构以适应生产代码的口味。我在这里做的是在删除我不再需要的迭代器之前将迭代器推进到一个安全节点。恐怕这是典型的迭代器失效
m_射弹。移除((*it))代码>使无效
。由for
循环执行的it++
将为您提供未定义的行为。那你的处境真的很糟糕
一个粗略的解决方案是使用
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)->isActive(){
std::list::iterator new_it=it;
++新的;/*我更喜欢这个而不是新的++*/
m_射弹。移除((*it));
it=新的it;
}否则{
++它;
}
作为if
语句的主体,删除for
循环中的it++
。重构以适应生产代码的口味。我在这里所做的是在删除不再需要的迭代器之前,将迭代器推进到一个安全节点。您最好使用一个合适的谓词:
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(); });
最好与适当的谓词一起使用:
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(); });
由于要从列表中删除的元素已有迭代器,因此不应使用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;
}
}
for(std::list::iterator it=m_projectles.begin();it!=m_projectles.end();/*正文中的增量*/)
{
if(!(*it)->isActive()//isActive返回bool
{
它=m_投射物。擦除(它);
}
其他的
{
++它;
}
}
当然,@juanchopanza的回答说明了如何使用标准算法而不完全使用循环来实现这一点。因为您已经有了要从列表中删除的元素的迭代器,所以不应该使用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;
}
}
for(std::list::iterator it=m_projectles.begin();it!=m_projectles.end();/*正文中的增量*/)
{
if(!(*it)->isActive()//isActive返回bool
{
它=m_投射物。擦除(它);
}
其他的
{
++它;
}
}
当然,@juanchopanza的回答说明了如何使用标准算法而不完全使用循环来实现这一点。您检查过指针是否有效吗?删除操作似乎很好,但列表中删除了一个条目,这使您检查过指针是否有效吗?删除操作似乎很好,但是列表中删除了一个条目,这是C++11吗+1.非常可爱。@Bathsheba我想它也是C++03。@juanchopanza我可以确认它在C++03:。@rightfold谢谢。我以前肯定用过它,只是不能100%确定它不是编译器扩展。@IanYoung在任何函数之外定义它。这是C++11吗+1.非常可爱。@Bathsheba我想它也是C++03。@juanchopanza我可以确认它在C++03:。@rightfold谢谢。我以前肯定用过它,只是不能100%确定它不是编译器扩展。@IanYoung在任何函数之外定义它。谢谢。我选择了这个,因为我不知道;我不需要在其他地方定义函数,但我真的希望我能将几个答案标记为已接受。谢谢大家!谢谢我选择了这个,因为我不知道;我不需要在其他地方定义函数,但我真的希望我能将几个答案标记为已接受。谢谢大家!