C++ 基礎からマスターまで — 第11回
ラムダと標準アルゴリズムの使用
本ブログ作成文は、講義を目指して製作されました。 また、作成された文章の情報も間違っている可能性がありますので、ご注意ください。
コンテナから特定のモンスターを探したり整列したり、死んだモンスターを削除するコードは頻繁に登場する。 for文で直接作成することもできますが、標準アルゴリズムを使用すると、コードの目的がよりよく見えます。
ラムダ
Lambdaは名前なしで直接書く関数です。
int monsterId = 10;
auto isTarget = [monsterId](const std::shared_ptr<Monster>& monster)
{
return monster->GetId() == monsterId;
};
[]はキャプチャリストです。 [monsterId]は値をコピーしてキャプチャし、[&]は外部変数を参照としてキャプチャします。[this]は現在のオブジェクトを使用します。
参照キャプチャは楽ですが、ラムダが元の変数より長く生き残ると危険です。 必要な値だけを明確にキャプチャする方がコードを読みやすい。
find_if
auto iter = std::find_if(
activeMonsters.begin(),
activeMonsters.end(),
[monsterId](const auto& monster)
{
return monster->GetId() == monsterId;
}
);
if (iter != activeMonsters.end())
{
currentTarget = *iter;
}
find_ifは条件を満たす最初の要素の反復子を返します。 見つからない場合は、渡した範囲の終了を返します。
sort
体力が低いモンスターからソートし、体力が同じならIDが低いモンスターを先に置くことができる。
std::sort(
activeMonsters.begin(),
activeMonsters.end(),
[](const auto& a, const auto& b)
{
if (a->GetHealth() != b->GetHealth())
{
return a->GetHealth() < b->GetHealth();
}
return a->GetId() < b->GetId();
}
);
比較関数がtrueを返すと、aがbの前に来なければならないことを意味します。 比較基準が互いに矛盾している場合、ソート結果は信じられないため、厳格な弱順を守る必要があります。
remove_ifとerase
auto newEnd = std::remove_if(
activeMonsters.begin(),
activeMonsters.end(),
[](const auto& monster)
{
return monster->IsDead();
}
);
activeMonsters.erase(newEnd, activeMonsters.end());
remove_ifはコンテナサイズを直接縮小しません。 残す元素を前に移し、新しい論理的な終わりを返す。実際の削除はeraseによって行われます。
vectorから要素が削除されると、後方の反復子と参照が無効になる可能性があります。 shared_ptr要素が削除されると参照数が減り、最後の所有者であればオブジェクトも破壊されます。
ラムダとアルゴリズムを使用してもコードが無条件に高速化されるわけではありません。 代わりに、検索、並べ替え、削除という意図がコードにそのまま現れるのが最大の利点です。