2015-12-09 34 views
0

我與我的multimap相關的「map/set iterator not incrementable」錯誤有問題。我試着用Google搜索答案,但答案並沒有幫助我。我假設的問題是,因爲我的代碼第一部分執行「akcja」命令,它可以(但不必)刪除multimap中的組件之一:}C++ map/set迭代器在使用multimap時不會增加錯誤

while ((c = getch()) != 27) 
    { 
     if (c == 'n') 
     { 
      typedef multimap<int, Organizm*>::iterator iterator; 
      for (int i = 10; i>= 0; i--) 
      { 
       std::pair<iterator, iterator> iterpair = kolejnoscRuchu.equal_range(i); 
       iterator it = iterpair.first; 

       for (; it != iterpair.second; ++it) 
       { 
        if(it->second->inicjatywa !=0) 
        { 
        it->second->akcja(); 
        } 
       } 
      } 

如果某些條件得到滿足的akcja()將觸發其除去該元素的命令:

void Swiat::usunOrganizm(Organizm *organizm) 
{ 
    this->organizmy[organizm->pozycja.x][organizm->pozycja.y] = NULL; 

    typedef multimap<int, Organizm*>::iterator iterator; 
    std::pair<iterator, iterator> iterpair2 = this->kolejnoscRuchu.equal_range(organizm->inicjatywa); 

    iterator it2 = iterpair2.first; 
    for (; it2 != iterpair2.second; ++it2) 
    { 
     if (it2->second == organizm) 
     { 
      cout << "usuwam " << it2->second->rysowanie() << endl; 
      kolejnoscRuchu.erase(it2); 
      delete organizm; 
      break; 
     } 
    } 
} 

我添加了一個「COUT < < 「usuwam」 < < it2->二階> rysowanie()「endl;」部分來確認從我的multimap中刪除任何元素後是否發生錯誤。我將不勝感激任何幫助

回答

1

如果你擦除在it2元素,那麼你不能再使用it2。增加它將不再可能。

你可以隨便寫一個迭代循環,其容忍的閉環控制自身的擦除:

iterator it = iterpair2.first; 
while (it != iterpair.second) 
{ 
    iterator next_it = it; 
    ++next_it; 
    /* it's possible for it to be deleted here */ 
    it = next_it; 
} 

但是,如果next_it在循環體擦除上面會失敗。所以,如果你想成爲更普遍的,你需要一個明確的比較:

while (it != iterpair.second) 
{ 
    iterator next_it = it; 
    ++next_it; 
    /* ... */ 
    if (some_condition) 
    { 
     /* Need to erase it_to_erase */ 
     if (it_to_erase == next_it) ++next_it; 
     theMap.erase(it_to_erase); 
    } 
    /* ... */ 
    it = next_it; 
} 

即使是要求代碼迭代也是其擦除元素的代碼。如果擦除代碼不相關(例如,因爲它在迭代中調用的函數中),那麼真的沒有解決方法允許立即擦除。

所以在這種情況下,你需要實現某種形式的延遲擦除。在OP中呈現的特定情況下,其中映射的mapped_type是其值不能爲空的指針,簡單形式的延遲擦除是簡單地將要擦除的元素的映射值設置爲0.

在簡單的延遲擦除方案下面,我假設外部循環本身是自由擦除元素;也就是說,它不在迭代過程中調用的函數中。爲簡單起見,我使用了一些C + 11功能。

/* Outer loop */ 

for (auto it = myMap.begin(), end = myMap.end();; ++i) { 
    /* Erase any previously marked elements */ 
    while (it != end && !it->second) it = myMap.erase(it); 
    if (it == end) break; 

    /* Do something with this element */ 
    /* ... */ 
    /* This function might "delete" arbitrary elements. See below */ 
    secondProcess(myMap); 
    /* At this point, "it" might not be valid, so you would need to 
    check before trying to use it. 
    */ 
} 

而這裏的內部函數:

void secondProcess(MapType& myMap) { 
    /* ... */ 
    for (auto it2 = myMap.begin(), end = myMap.end(); it2 != end; ++it2) { 
    if (it2->second) { /* Make sure the element is not already marked */ 
     /* ... */ 

     /* Here we've decided to erase the element at "it2" 
     * The delete comes from the code in OP; it is only OK if the 
     * mapped value is the only pointer to the object it points to. 
     */ 
     delete it2->second; 
     it2->second = 0; 
     /* Since we don't actually erase it2, no other adjustment 
     * is needed 
     */ 
    } 
    } 
} 
+0

謝謝,但我不知道這是否解決方案將一直幫助我。基本上在我的例子中,我有2個迭代器,因爲我的multimap是一個有機體的容器,其各自的主動性值在0-10範圍內。當生物體移動時,它可以與另一個生物體作戰,如果發生戰鬥,其中一個將會死亡 - 因此是第二個迭代器。你的解決方案讓我迭代第二個循環,但是如果我在「usunOrganizm」函數中刪除第一個迭代器會怎麼樣? –

+0

@LKaniewski:好的,增加了另一種可能的解決方案。 – rici