2016-03-28 4 views
0

私のクラスでは、ループを使用してstd::vectorから要素を削除しようとしています。しかし、要素を削除しようとすると、エラーが発生し、解決方法がわかりません。私が手にエラーがある:ベクトルの要素を位置によって削除しますか?

エラー4エラーC2679:バイナリ「+」:なしオペレータは

タイプ「敵*」の右側のオペランドをとる(または全く許容される変換は存在しない)が見つかりません
void Enemy::UpdateEnemies(SDL_Renderer * render) 
{ 
    for (int i = enemies.size() - 1; i >= 0; i--) 
    { 
     enemies[i]->Update(); 
     if (enemies[i]->Active == false) 
     { 
      // Receive the error here 
      enemies.erase(enemies.begin() + enemies.at(i));    
     } 
    } 
    if ((SDL_GetTicks()-prevSpawnTime)/1000.0f > enemySpawnTime) 
    { 
     prevSpawnTime = SDL_GetTicks(); 
     //Add an anemy 
     AddEnemy(render); 
    }  
} 
+0

は、私はあなたが 'enemies.erase(enemies.begin()+ i)を意味だと思う;' – DimChtz

+0

@DimChtz笑気にしません。私は前にそれを試していました。なぜなら、私はアクティブな変数を宣言していますが、それを初期化していないからです。私の悪いが、ありがとう。 – RoundSquare

答えて

1

他の答えはあなたの素朴な解決策を与えています。しかし、複数の敵を取り除く場合は、より良い解決策が必要です。

std::remove_if<algorithm>から使用する方が良いでしょう。これはあなたのベクトルの項目の繰り返しシャッフルを避けることができます。削除するすべてのオブジェクトをコンテナのエンドに移動し、それらの先頭までイテレータを渡します。

auto removed_iter = std::remove_if(enemies.begin(), enemies.end(), 
            [](const Enemy * e) { return e->IsActive(); }); 

enemies.erase(removed_iter, enemies.end()); 

この場合、すべての敵を最初に更新する必要があります。それは、その後、逆の順序で行われる必要がない場合:他の人が言ったこと、私はさらに一歩それを取ると、ループ内のベクトルから消去することは未定義引き起こす可能性があることを示唆していることに加え

for(auto e : enemies) e->Update(); 
+1

Upvoted、これは一般的な方法です。 – vsoftco

+0

このコードはC++ 11以降のものです。これらの日を実際に述べる必要はありませんが、古いコンパイラを使用している人もいます。また、私が 'const Enemy *'を渡しているという事実は、const-correctnessで 'Enemy :: IsActive'を実装することを要求しています。コンパイルエラーがある場合は、それを考慮してください。 – paddy

2

あなたはi番目の要素を削除すると仮定すると、あなたは

enemies.erase(enemies.begin() + i); 

またはより良い

を行う必要があります位置 i、即ちタイプ Enemyの要素ではなく、 i又は位置 iのイテレータで間接参照イテレータを返し enemies.at(i)あなたの場合
enemies.erase(std::next(enemies.begin(), i)); 

良い方法は、逆反復子を使用することである。

for(auto it = enemies.rbegin(); it != enemies.rend(); ++it) 
{ 
    (*it)->Update(); 
    if ((*it)->Active == false) 
    { // need `base()` to convert to regular iterator, then substract 1 
     enemies.erase(std::prev(it.base())); // remove the current position 
     /* or, equivalently 
     enemies.erase(std::next(it).base()); 
     */ 
    } 
} 
0

この行:

enemies.erase(enemies.begin() + enemies.at(i)); 
  • enemise.at(i)は、ベクターに格納されている敵を返します。
  • enemies.begin()エラーは、あなたがポインタとベクトルを追加しようとしている、言うようにポインタ

です。あなたはおそらく呼び出したい

enemies.erase(enemies.begin() + i); 
0

を動作。私は休憩を見ないので、複数の非アクティブな敵が存在する可能性があると仮定します。独自のループを書く代わりに、std :: remove_ifアルゴリズムの使用を検討してください。基本的に、コードはコンパイルに失敗するオブジェクト参照を持つイテレータを追加しようとしています。 remove_ifの解決策は、本質的にActive == falseのすべての敵をコンテナの最後にコピーし、他のものはすべて前方に移動させます。これは、削除するものを最初に識別し、一度にそれらをすべて消去する便利な方法を提供します。さらに、C++ 11コンパイラを使用していない場合は、別の種類の述語を使用しても同じことが動作します。 remove_ifリンクには関数の例が含まれていますが、ファンクタを使用することもできます。

enemies.erase(std::remove_if(enemies.begin(), enemies.end(), [](const Enemy* e){ return e->Active == false; }), enemies.end()); 

詳細については、これらを確認してください。

What is a lambda expression in C++11?

http://www.cplusplus.com/reference/algorithm/remove_if/

C++ Functors - and their uses

関連する問題