C++ von den Grundlagen bis zum Profi — Folge 11
Lambdas und Standardalgorithmen verwenden
Die in diesem Blog verfassten Artikel wurden mit dem Ziel erstellt, zu unterrichten. Außerdem können die Informationen im Artikel falsch sein, also seien Sie bitte vorsichtig.
Code zum Suchen oder Sortieren bestimmter Monster in einem Container und zum Entfernen toter Monster erscheint häufig. Sie können Ihre eigene mit einer for-Anweisung erstellen, aber die Verwendung eines Standardalgorithmus macht den Zweck des Codes besser sichtbar.
Lambda
Ein Lambda ist eine Funktion, die Sie direkt ohne Namen schreiben.
int monsterId = 10;
auto isTarget = [monsterId](const std::shared_ptr<Monster>& monster)
{
return monster->GetId() == monsterId;
};
[]ist die Capture-Liste. [monsterId]erfasst den Wert durch Kopieren,[&]erfasst externe Variablen per Referenz.[this]verwendet das aktuelle Objekt.
Die Referenzerfassung ist praktisch, kann jedoch gefährlich sein, wenn das Lambda länger überlebt als die ursprüngliche Variable. Der Code ist einfacher zu lesen, wenn Sie nur die notwendigen Werte klar erfassen.
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 gibt einen Iterator des ersten Elements zurück, das die Bedingung erfüllt. Wenn nicht gefunden, wird das Ende des übergebenen Bereichs zurückgegeben.
sort
Sortieren Sie zuerst die Monster mit der niedrigsten Gesundheit, und wenn die Gesundheit gleich ist, können Sie die Monster mit der niedrigeren ID zuerst platzieren.
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();
}
);
Wenn die Vergleichsfunktion „true“ zurückgibt, bedeutet dies, dass a vor b stehen muss. Bei widersprüchlichen Vergleichskriterien kann den Sortierergebnissen nicht vertraut werden, sodass eine strikte Kurzreihenfolge einzuhalten ist.
Remove_if und löschen
auto newEnd = std::remove_if(
activeMonsters.begin(),
activeMonsters.end(),
[](const auto& monster)
{
return monster->IsDead();
}
);
activeMonsters.erase(newEnd, activeMonsters.end());
Mit „remove_if“ wird die Containergröße nicht direkt reduziert. Verschiebt die verbleibenden Elemente nach vorne und gibt das neue logische Ende zurück. Die eigentliche Löschung erfolgt durch Erase.
Wenn ein Element aus einem Vektor gelöscht wird, werden nachfolgende Iteratoren und Referenzen möglicherweise ungültig. Wenn ein shared_ptr-Element entfernt wird, wird sein Referenzzähler dekrementiert, und wenn es der letzte Besitzer war, wird das Objekt ebenfalls zerstört.
Die Verwendung von Lambda und Algorithmen macht den Code nicht unbedingt schneller. Der größte Vorteil besteht vielmehr darin, dass die Absicht des Suchens, Sortierens und Entfernens klar im Code zum Ausdruck kommt.