首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >std容器迭代器在擦除过程中的失效

std容器迭代器在擦除过程中的失效
EN

Stack Overflow用户
提问于 2011-06-26 21:41:46
回答 2查看 844关注 0票数 3

可能重复:

vector erase iterator

Problem with std::map::iterator after calling erase()

我关心的是我的一段代码。我有组件和存储组件的对象。问题是,在更新过程中,组件可以告诉从对象中删除组件。但它是从另一个函数调用的。

代码语言:javascript
复制
void Object::update() { //using std::map here
   for(ComponentMap::iterator i = components.begin(); i != components.end(); ++i) {
      (*i).second->update();
   }
}

void HealthComponent::update() {
   if(health <= 0) object->removeComponent("AliveComponent"); //this is wrong logic. but its just an example :D
}

void Object::removeComponent(string component) {

  ComponentMap::iterator i = components.find(component);
  if(i == components.end()) return;

  components.erase(i);

}

假设我有很多组件--健康,生命,图形,物理,输入等等。

我尝试过这样的方法(包括一些测试组件),并且在更新过程中没有错误。但我真的很担心。将来它能让我犯错误吗?如果是的话,怎么解决呢?

提前谢谢你,

加西姆

EN

回答 2

Stack Overflow用户

发布于 2011-06-26 21:46:17

++i可能不再有效时,不能循环遍历容器并说i (因为您删除了它)。典型的擦除循环如下:

代码语言:javascript
复制
for (it = x.begin(); it != x.end(); /* nothing here! */)
{
  if (must_erase(*it))
  {
    x.erase(it++); // advance it while still valid, return previous and erase
  }
  else
  {
    ++it;
  }
}

以这种精神重写您的代码。

要说明您的问题:在Object::update()中,调用HealthComponent::update()使迭代器i无效,然后调用++i,这是未定义的行为。

票数 7
EN

Stack Overflow用户

发布于 2011-06-26 22:26:09

在MSVC中,擦除将返回下一个有效的迭代器,而在GCC中返回无效,因此处理此问题的唯一可移植方法是保留前一个迭代器,删除当前元素,然后在下一次迭代中递增前一个迭代器。

http://www.cplusplus.com/reference/stl/map/erase/

代码语言:javascript
复制
  void Object::removeComponent(string component, ComponentMap::iterator& _prev ) 
  {
     ComponentMap::iterator i = components.find(component);
     if(i == components.end()) 
        return;
     _prev = i;
     --_prev;
     components.erase(i);
     ++prev;
   }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6486922

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档