可能重复:
vector erase iterator
Problem with std::map::iterator after calling erase()
我对我的一段代码感到担忧。我有组件和存储组件的对象。问题是在组件可以告知从对象中删除组件的更新期间。但它从另一个函数调用。
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);
}
并假设我有很多组件 - 健康,活着,图形,物理,输入等。
我尝试了类似的东西(带有一些测试组件),并且在更新期间没有错误。但我真的很担心。它可以在将来给我一个错误吗?如果是的话,如何解决?
提前致谢,
卡西姆
答案 0 :(得分:6)
当++i
可能不再有效时(因为您已将其删除),您无法遍历容器并说出i
。典型的擦除循环如下:
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
,这是未定义的行为。
答案 1 :(得分:0)
在MSVC中,erase将返回下一个有效的迭代器,但是在GCC中它返回void,因此处理此问题的唯一可移植方法是保留前一个迭代器,擦除当前元素,然后递增前一个迭代器以进行下一次迭代。
http://www.cplusplus.com/reference/stl/map/erase/
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;
}