この質問と似たような質問があることは知っていますが、彼らの助けを借りて自分のコードの道を見つけることができませんでした。ループ内でこの要素の属性をチェックすることで、ベクトルの要素を単に削除/削除したいだけです。どうやってやるの?次のコードを試しましたが、あいまいなエラーメッセージが表示されます。
「operator =」機能は「Player」では使用できません。
for (vector<Player>::iterator it = allPlayers.begin(); it != allPlayers.end(); it++)
{
if(it->getpMoney()<=0)
it = allPlayers.erase(it);
else
++it;
}
私は何をすべきか?
更新:質問 vector :: erase with pointer member は同じ問題に関係すると思いますか?したがって、割り当て演算子が必要ですか?どうして?
it
ループでfor
をインクリメントしないでください:
_for (vector<Player>::iterator it=allPlayers.begin();
it!=allPlayers.end();
/*it++*/) <----------- I commented it.
{
if(it->getpMoney()<=0)
it = allPlayers.erase(it);
else
++it;
}
_
it
がfor-body自体でインクリメントされるため、コメント部分; _it++
_は必要ありません。
エラー「 'operator =' function is in available in 'Player'」については、erase()
の使用に起因します。内部で_operator=
_を使用してベクター内の要素を移動します。 erase()
を使用するには、クラスPlayer
のオブジェクトが割り当て可能である必要があります。つまり、Player
クラスに_operator=
_を実装する必要があります。
とにかく、避ける必要があります rawループ1 可能な限り、代わりにアルゴリズムを使用することを選択する必要があります。この場合、人気のある Erase-Remove Idiom を使用すると、作業を簡素化できます。
_allPlayers.erase(
std::remove_if(
allPlayers.begin(),
allPlayers.end(),
[](Player const & p) { return p.getpMoney() <= 0; }
),
allPlayers.end()
);
_
1.それは Sean Parentによる最高の話 の1つです。
if(allPlayers.empty() == false) {
for(int i = allPlayers.size() - 1; i >= 0; i--) {
if(allPlayers.at(i).getpMoney() <= 0) {
allPlayers.erase( allPlayers.begin() + i );
}
}
}
これはベクター内の要素を削除する私の方法です。理解しやすく、トリックは必要ありません。
ループを忘れて、stdまたはboost範囲アルゴリズムを使用します。
LambdaでBoost.Rangeを使用すると、次のようになります。
boost::remove_if( allPlayers, bind(&Player::getpMoney, _1)<=0 );
具体的な問題は、Player
クラスに代入演算子がないことです。 「プレイヤー」をベクターから削除するには、コピー可能または移動可能にする必要があります。これは、ベクトルが連続している必要があるため、要素を削除するときに作成されたギャップを埋めるために要素を並べ替える必要があるためです。
また:
Stdアルゴリズムを使用
allPlayers.erase(std::remove_if(allPlayers.begin(), allPlayers.end(), [](const Player& player)
{
return player.getpMoney() <= 0;
}), allPlayers.end());
ブーストがある場合はさらに簡単です:
boost::remove_erase_if(allPlayers, [](const Player& player)
{
return player.getpMoney() <= 0;
});
C++ 11ラムダのサポートがない場合は、TimWの回答を参照してください。
または、逆方向にループします。
for (vector<Player>::iterator it = allPlayers.end() - 1; it != allPlayers.begin() - 1; it--)
if(it->getpMoney()<=0)
it = allPlayers.erase(it);
C++ 11は、ここで使用する新しい関数のコレクションを導入しました。
allPlayers.erase(
std::remove_if(allPlayers.begin(), allPlayers.end(),
[](auto& x) {return x->getpMoney() <= 0;} ),
allPlayers.end());
そして、エンド要素をそれほどシフトする必要がないという利点が得られます。
遅い答えですが、非効率的なバリアントを見たとして:
std::remove
または std::remove_if
は進むべき道です。要素を効率的に削除するためのコード:
auto pos = container.begin();
for(auto i = container.begin(); i != container.end(); ++i)
{
if(isKeepElement(*i)) // whatever condition...
{
*pos++ = *i; // will move, if move assignment is available...
}
}
// well, std::remove(_if) stops here...
container.erase(pos, container.end());
このようなループを明示的に記述する必要があるかもしれませんe。 g。エレメント自体を削除するかどうかを判断するためにイテレーター自体が必要な場合(条件パラメーターはエレメントへの参照を受け入れる必要がありますか?)。 g。後継者/前任者との特定の関係により(ただし、この関係が平等である場合、 std::unique
)。