我有一个奇怪的问题,很少发生与我在以下示例代码中简化的无效STL迭代器有关。
#include "Bar.h"
#include <map>
class Foo
{
std::map<int, Bar*> test;
public:
Foo() {}
void Update();
void AddEntry(int i, Bar* bar);
void DeleteEntry(int i);
};
#include "Foo.h"
void Foo::Update() {
for(auto iter = test.rbegin(); iter != test.rend(); iter++) {
iter->second->DoThingOne();
iter->second->DoThingTwo(); // BREAKS ON 2nd ITERATION
}
}
void Foo::AddEntry(int i, Bar* b) {
test[i] = b;
}
void Foo::DeleteEntry(int i) {
delete test[i];
test.erase(i);
}
class Foo;
class Bar
{
Foo* f;
static int count;
public:
friend class Foo;
Bar(Foo* f_);
void DoThingOne();
void DoThingTwo();
};
#include "Bar.h"
#include "Foo.h"
int Bar::count = 0;
Bar::Bar(Foo* f_) : f(f_) {}
void Bar::DoThingOne() {
if(count++ == 1) {
f->DeleteEntry(3);
}
}
void Bar::DoThingTwo() {
// Does things
}
#include "Foo.h"
int main() {
Foo* foo = new Foo();
Bar* one = new Bar(foo);
Bar* two = new Bar(foo);
Bar* three = new Bar(foo);
foo->AddEntry(1, one);
foo->AddEntry(2, two);
foo->AddEntry(3, three);
foo->Update();
return 0;
}
所以基本上,当调用Foo::Update
时,循环的第一次迭代正常进行,然后第二次迭代调用DoThingOne,它删除地图中刚才使用的循环的前一次迭代的条目。在我得到&#34; Debug Assertion失败后立即调用DoThingTwo
时!表达式:map / set iterator不可递减&#34;错误导致程序崩溃。
根据我的理解,映射和集合上的迭代器总是有效的,除了引用已删除元素的迭代器,但是迭代器在删除一个元素之后引用该元素。我唯一的猜测是,它与被删除的元素是第一个/最后一个元素有关,然后使用的迭代器是指新的第一个/最后一个元素,但我仍然无法找到确切的原因正在发生或如何解决它。我只能选择在调用DoThingTwo之前检测for循环中是否发生这种情况并尝试在那里修复它。
编辑:在查看Nemo提供的链接后,我将循环更改为以下内容并且似乎有效:
void Foo::Update {
auto iter = test.end();
for(iter--; iter != test.begin(); iter--) {
iter->second->DoThingOne();
iter->second->DoThingTwo();
}
iter->second->DoThingOne();
iter->second->DoThingTwo();
}
看起来很草率,但确实可以完成工作。由于使用迭代器而不是reverse_iterator,我认为它确实与reverse_iterator与迭代器相比如何工作。