2016-11-12 5 views
0

std::unique_ptr<Enemy>のベクトルを反復処理して、playerの攻撃と衝突しているかどうかを確認しようとしています。もしそうなら、私はベクトルからEnemyを削除したいと思う。Vectorから要素を反復して削除する。エラー:ベクトルイテレータがインクリメント可能ではありません

ファイル:C:私はこれを行うとき はしかし、私はエラーを取得102 式:

ベクトルイテレータincrementableないマイクロソフトのVisual Studio 14.0 \ VCの\ \ \プログラムファイル(x86のを)\ベクトル ラインを含めますプレイヤーが攻撃をトリガーする場合

if(actionCnt > 0) 
{ 
    sf::FloatRect* playerAction = player->action(actionCnt); 

    if (!enemies.empty()) { 
     for (auto&i : enemies) { 
      if (playerAction->intersects(i->getBox())) { 
       i->kill(); 
       enemies.erase(std::remove(enemies.begin(), enemies.end(), i)); 
      } 
     } 
    } 

    delete playerAction; 
    playerAction = NULL; 
} 

ので、基本的に、actionCntが1になり、このセグメントが実行されます:

は、ここでは、コードです。

playerActionは、スイングをシミュレートするために移動される矩形ですので、ここでは、矩形が敵と衝突している場合はそれを殺すことになります。

私はSFMLライブラリを使用していますが、クラスが何をしているのかは明らかです。

今私は、この物をテストするためにフィールドに1人の敵しかいません。だから、私がヒットしたら、enemiesベクトルは空でなければならない。

+5

これが問題であるかどうかに関わらず、 'for'の範囲で反復処理をしながら'消去 'したくないと信じてください。 – user4581301

+0

[ベクトルからの要素の消去]の可能な複製(http:// stackoverflow。com/questions/347441/erasing-elements-from-a-vector) – LogicStuff

+0

投稿されたスレッド@LogicStuffを見て、whileループに入れようとしていますが、 'たとえば、イテレータ を使用してenemies'ベクトル: ' playerAction->交差(* iter-> getBox()) ' は私にエラーを与えると言って ' "のstd :: unique_ptrを<敵、のstd :: default_delete >" "getBox"のメンバーはありません。 – Ausche

答えて

5

コード内のautoは、ベクターコンテナ内の型を返します。それはあなたにイテレータを与えるものではありません。範囲ベースのforループの代わりに、古典的なforループを使用して、イテレータで要素を消去することができます。

if (!enemies.empty()) 
{ 
    for (auto itr = std::begin(enemies); itr!=std::end(enemies); ++itr) 
    { 
     if ((*itr)->hit) 
     { 
      (*itr)->kill(); 
      enemies.erase(itr); 
     } 
    } 
} 

または、std :: remove_ifの中でラムダ関数を使用して、すべての行を1行で実行できます。これは実際にイレーズ・イディオム(more here)として知られています。簡単に言えば、remove_ifは、ラムダ関数から偽を返すコンテナ内のすべての要素を保存順序に従ってシフト(移動)し、最後の要素を過ぎたものにイテレータを返します。ラムダ関数から真を返す要素はベクトルの終わりに移動され、引き続き参照不可能ですが未定義です。要素を完全に消去するには、ベクトルの消去関数を呼び出して、論理終わり(std :: remove_ifのイテレーター)からコンテナーの物理終端(vector.end())までのすべての要素を削除します。 forループの範囲であったベースのさらに

if (!enemies.empty()) 
    enemies.erase(std::remove_if(enemies.begin(),enemies.end(),[](const auto &itr){return itr->hit;}),std::end(enemies)); 

は、あなたがあなたの要素にアクションを実行するために コンテナ自体を変異させずにワン際に使用されます。より安全なコードでは、範囲ベースのforループの代わりにwhileループを使用できます。 http://rextester.com/EHLB11709 私は、削除部分にのみ焦点を当て、あなたのゲームロジックを真似してみました:

if (!enemies.empty()) 
{ 
    auto itr = std::begin(enemies); 
    while (itr != std::end(enemies)) 
    { 
     if ((*itr)->hit) 
     { 
      (*itr)->kill(); 
      enemies.erase(itr); 
     } 
     ++itr; 
    } 
} 

あなたはここにコードを見てすることができます。出力から、6番目の要素が削除されたことがわかります。

さらに、ベクターからすべてを削除する場合は、clear()を使用する必要があります。

関連する問題