2016-02-03 71 views
1

這裏有一個小的代碼,這是使我們有點瘋了......重置迭代器與擦除方法

for (vector<QSharedPointer<Mine>>::iterator itMine = _mines.begin(); 
     itMine != _mines.end();) { 
    auto point2 = shipFire[l].getBulletLine().p2(); 
    if (_mines[pos]->checkCollision(point2)) { // _mines is a Vector<QSharedPointer<Mine>> 
     Explosion explosionMine(_mines[pos]->point()); 
     _explosions.push_back(explosionMine); 
     itMine = _mines.erase(itMine); 
     bulletErased = true; 
     scoreFrame += 100; 
    } 
    else { 
     ++itMine; 
     pos++; 
    } 
} 

這裏的問題是,在itMine被刪除我們的兩個vector<..<Mine>>的,它的製作程序意外關閉

我們想過這個問題,以及與此想出了:我們所有的迭代器被擦除礦一前一後無效,對不對?

但我們是一個有點困惑如何改變我們的實際代碼以適應新的?

的主要問題是:我們如何重置此ITR?

PS:如果您有任何疑問,或者您需要多一點的代碼來理解背後的邏輯,隨意問更多的問題!

最好的問候,並提前感謝您。

+2

'_mines [POS]'和使用迭代器種類衝突的。您可能想重新考慮這一點。爲什麼不直接使用迭代器? – user4581301

+1

[This](https://ideone.com/HKcjSM)在邏輯上類似於你所擁有的並且工作得很好(也就是說,你可以增加迭代器或者使用'erase'函數返回的值來安全地循環所有的元件)。 –

+1

[查看刪除 - 刪除成語是否適合您](http://stackoverflow.com/questions/347441/erasing-elements-from-a-vector) – user4581301

回答

0

更新


for (auto itMine = _mines.begin(); itMine != _mines.end();){ 
      auto point2 = shipFire[l].getBulletLine().p2(); // thomas : -> here we need to do it in the loop, to get every bullet position while looping. 

      if (_mines[pos]->checkCollision(point2)){ 
       Explosion explosionMine(_mines[pos]->point()); 
       _explosions.push_back(explosionMine); 
       if (_mines[pos]->checkCollision(point2)){ 
        mines_to_be_deleted.push_back(*itMine); 
        shipFire.erase(it); 
        bulletErased = true; 
        scoreFrame += 100; 
        qDebug() << "Collision bullet mine"; 

       } 
      } 
      //else 
      ++itMine; 
      pos++; 
     } 


     for (auto itrDelete = mines_to_be_deleted.begin(); itrDelete != mines_to_be_deleted.end();) 
     { 
       _mines.pop_back(); // Here instead of that, we need to erase the current itr (here is our mistake) 
       //mines_to_be_deleted.erase(itrDelete); 
       //_mines.resize(_mines.size()); 
       qDebug() << "mine deleted"; 
       ++itrDelete; 
     } 
     mines_to_be_deleted.clear(); 

在這一點上,我們想出了這個。 我們試過了你告訴我們的一切,但都沒有工作,我們考慮將當前的itr換成矢量的末尾。謝謝你的幫助。

目前,該程序運行完美,但是當我們打了礦用一顆子彈,一個ramdom一個disapear。

對於那些想知道的人,我們找到了解決方案。

while(!mines_to_be_deleted.empty()) { // _mine_to_be_deleted is a QList<Sharedpointer<Mine>> 
     std::remove(begin(_mines),end(_mines),mines_to_be_deleted.front()); 
     _mines.pop_back(); 
     mines_to_be_deleted.pop_front(); 
    } 

使用std ::刪除讓我們清除地雷,而無需創建一個malloc()

0

甲並不少見的解決這個問題是交換與背部位置的當前位置。然後可以刪除最後一項,而不會使任何迭代器失效。請參閱live example

#include <iostream> 
#include <vector> 
#include <memory> 

int main() 
{ 
    struct Mine 
    { 
     Mine(int id = 0): id(id) { } 
     bool check_collision_point(int point) const { return id % point == 0; } 
     int id; 
    }; 

    auto mines = std::vector<std::shared_ptr<Mine>>{ 7 }; 

    for(auto i = 0u; i < mines.size(); ++i) 
    { 
     mines[i] = std::make_shared<Mine>(i); 
    } 

    // save point outside loop 
    auto point = 2; 

    for(auto it = mines.begin(); it != mines.end();) 
    { 
     // don't use mines[pos] in loop 
     if((*it)->check_collision_point(point)){ 
      std::iter_swap(it, mines.rbegin()); 
      mines.resize(mines.size() -1); 
     } 
     else 
      ++it; 
    } 

    for(auto it = mines.begin(); it != mines.end(); ++it) 
     std::cout << (*it)->id << " "; 
} 
+1

[This](http:// coliru .stacked-crooked.com/a/fcd311d0b38b12e9)工作得很好,無需使用交換。我還要提到在主註釋中由@ user4581301提到的擦除刪除習慣用法對於OP可能是有用的(即,而不是手動交換和擦除)。 –

+0

@James Adkison我同意你的解決方案更加緊湊和優雅,但從大型矢量中移除少量項目時效率會更低。 – Thomas

+0

是的,這是使用刪除成語的原因。我只是指出你的答案不是解決OP問題所必需的。 –