检测并修复无效的迭代器

时间:2015-05-24 03:40:16

标签: c++ dictionary iterator dereference invalidation

我有一个奇怪的问题,很少发生与我在以下示例代码中简化的无效STL迭代器有关。

foo.h中

#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);
};

Foo.cpp中

#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);
}

Bar.h

class Foo;
class Bar
{
    Foo* f;
    static int count;
public:
    friend class Foo;
    Bar(Foo* f_);
    void DoThingOne();
    void DoThingTwo();
};

Bar.cpp

#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
}

Main.cpp的

#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();
}

看起来很草率,但确实可以完成工作。由于使用迭代器而不是rev​​erse_iterator,我认为它确实与reverse_iterator与迭代器相比如何工作。

0 个答案:

没有答案