簡體   English   中英

使用Multimap時C ++映射/設置迭代器不增加錯誤

[英]C++ map/set iterator not incrementable error while using multimap

與多圖有關的“映射/集迭代器不可遞增”錯誤。 我曾嘗試使用Google搜索來尋找答案,但是答案並沒有幫助我。 我假設問題是因為我的代碼的第一部分執行了“ akcja”命令,該命令可能(但不必)刪除多圖的一個組件:

    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-> second-> rysowanie()<< endl;” 部分以確認從我的多重地圖中刪除任何元素后是否發生錯誤。 我將不勝感激任何幫助

如果你在刪除元素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是其值不能為null的指針,延遲擦除的一種簡單形式是簡單地將要擦除的元素的映射值設置為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 
        */
    }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM