2014-03-25 49 views
0

當我通過調試器一步一步地運行程序時,我不會收到此錯誤。然而,當我真正運行程序時,我每次都會得到它。它打破這個循環:列表迭代器不兼容

auto ships = sprites.begin(); 
auto misscnt = sprites.begin(); misscnt++; misscnt++; //missiles start at the 3rd item on list every time. 

while (misscnt != sprites.end())  //Missile Collision 
    { 
     ships = sprites.begin(); 
     ships++; 
     if (dynamic_cast<Missile*>(*misscnt)->Collides((*ships)->GetLeft(), (*ships)->GetTop(), (*ships)->GetWidth(), (*ships)->GetHeight()) && dynamic_cast<Missile*>(*misscnt)->GetID() == "PlayerMiss") 
     { 
      ships--; 

      (*ships)->AddToScore(10); 
      sys->playSound(FMOD_CHANNEL_FREE, eHit, false, 0); 
      while (true) 
      { 
       ships = sprites.begin(); 
       ships++; 
       int x, y; 
       x = rand() % Console::WindowWidth; 
       y = rand() & Console::WindowHeight; 
       if ((*ships)->GoodSpot(x, y, *(*--ships))) 
       { 
        ships++; 
        (*ships)->SetLeft(x); 
        (*ships)->SetTop(y); 
        break; 
       } 
      } 
      delete (*misscnt); 
      sprites.erase(misscnt); 
      ships = sprites.begin(); 
     } 

     else if (dynamic_cast<Missile*>((*misscnt))->Collides((*ships)->GetLeft(), (*ships)->GetTop(), (*ships)->GetWidth(), (*ships)->GetHeight()) && dynamic_cast<Missile*>((*misscnt))->GetID() == "EnemyMiss") 
     { 
      (*ships)->SetLives((*ships)->GetLives() - 1); 
      if ((*ships)->GetLives() > 1) 
       sys->playSound(FMOD_CHANNEL_FREE, pHit, false, 0); 
      if ((*ships)->GetLives() == 1) 
       sys->playSound(FMOD_CHANNEL_FREE, LastLife, false, 0); 
      if ((*ships)->GetLives() == 0) 
      { 
       bgmusic->setPaused(true); 
       sys->playSound(FMOD_CHANNEL_FREE, pDie, false, 0); 
       Sleep(4000); 
       play = false; 
       break; 
       } 
      while (true) 
      { 
       int x, y; 
       x = rand() % Console::WindowWidth; 
       y = rand() & Console::WindowHeight; 
       if ((*ships)->GoodSpot(x, y, *(*++ships))) 
       { 
        ships--; 
        (*ships)->SetLeft(x); 
        (*ships)->SetTop(y); 
        break; 
       } 
      } 
      delete (*misscnt); 
      sprites.erase(misscnt); 
      ships = sprites.begin(); 
     } 
     else 
      misscnt++; 
    } 

該計劃從未進入任如果還是否則,如果機構因此每當導彈被觸發它被添加到列表中。在循環中,如果導彈在任何情況下不會碰撞,它應該增加misscnt並檢查下一個導彈(如果有的話)。

編輯:錯誤說

列表迭代不相容 文件:: F:\ VS2013 \ VC \包括\目錄 線:289

我覺得行談論的文件 「列表」 。

當它打破VS指向while循環條件,說它是下一行要執行。

+0

什麼是確切的錯誤和它是什麼行? –

+1

舊的「用迭代器循環時擦除迭代器」的困境。如果你只是使用std :: partition並對死船進行分區,然後在該循​​環之外刪除/擦除它們,那將更容易。如果您沒有使用dynamic_cast,而是使用適當的OO技術(如虛擬功能),它也會有所幫助。 – PaulMcKenzie

+0

@PaulMcKenzie我們還沒有被教過分區,所以我不能使用它。另外,船隻不會死亡。只是導彈。 dynamic_cast真的會引起我所看到的問題嗎? – user3334986

回答

2

while()循環中有很多事情要做。它應該被重構,以便它不會使用無效的迭代器來獲取這些問題。下面的代碼沒有被編譯,但它會被用來試圖說明我的觀點:

#include <algorithm> 

bool IsAlive(ships& s) 
{ return s.IsActive(); } 

void DeleteMe(ship& s) 
{ delete &s; } 

//... 
auto ships = sprites.begin(); 
auto misscnt = sprites.begin(); 
std::advance(misscnt, 2); 

while (misscnt != sprites.end())  //Missile Collision 
{ 
    // do the collision handling 
    bool hasCollided = DoCollisionHandling(misscnt); 
    if (hasCollided) 
     misscnt->setActive(false); 
    ++misscnt; 
} 

// remove the inactive ones 
list<sprites>::iterator pt = std::partition(sprites.begin(), sprites.end(), IsAlive); 
std::for_each(pt, sprites.end(), DeleteMe); 
std::erase(pt, sprites.end()); 

給你貼什麼,上面的代碼應該是你想達到什麼樣的一個概要。請注意,唯一完成的是調用DoCollisionHandling(它應該是一個虛函數,爲每種類型重寫),並返回是否發生衝突。 DoCollisionHandling()應該而不是是擦除項目。

然後在while循環之外,我們將死去的分區分割到分區的右邊,這樣我們就可以刪除它們(或者做任何我們以後想做的事情)。 「pt」是迭代器,它是活着和死亡之間的分界線。

有可能有更好的方法來做到這一點,但我不建議的一種方法是試圖在這樣的循環中過於可愛,因爲在這種情況下,您正在刪除正在迭代的項目。除非是玩具或簡單的循環,否則做這樣的事似乎總是會造成麻煩。最好只標記這些項目,並稍後處理它們。