Lambdaausdruckssyntax

Dieser Artikel beschreibt Syntax und Strukturelemente von Lambdaausdrücken. Eine Beschreibung von Lambda-Ausdrücken finden Sie unter Lambda-Ausdrücke.

Funktionsobjekte und Lambdas

Wenn Sie Code schreiben, verwenden Sie wahrscheinlich Funktionszeiger und Funktionsobjekte, um Probleme zu lösen und Berechnungen auszuführen, insbesondere wenn Sie C++-Standardbibliotheksalgorithmen verwenden. Funktionszeiger und Funktionsobjekte haben beide Vorteile und Nachteile – z. B. weisen Funktionszeiger minimalen syntaktischen Mehraufwand auf, behalten aber innerhalb eines Bereichs den Zustand nicht bei. Hingegen können Funktionsobjekte den Zustand zwar beibehalten, erfordern allerdings den syntaktischen Mehraufwand einer Klassendefinition.

Bei einem Lambda werden die Vorteile von Funktionszeigern und Funktionsobjekten kombiniert und deren Nachteile gleichzeitig vermieden. Wie ein Funktionsobjekt ist eine Lambda-Funktion flexibel und kann Standard Zustand enthalten, aber im Gegensatz zu einem Funktionsobjekt erfordert die kompakte Syntax keine explizite Klassendefinition. Mit der Verwendung von Lambdas können Sie Code schreiben, der weniger schwerfällig und weniger fehleranfällig als Code für ein entsprechendes Funktionsobjekt ist.

In den folgenden Beispielen wird die Verwendung eines Lambda-Ausdrucks mit der Verwendung eines Funktionsobjekts verglichen. Im ersten Beispiel wird ein Lambda-Ausdruck verwendet, um auf der Konsole auszugeben, ob jedes Element in einem vector-Objekt gerade oder ungerade ist. Im zweiten Beispiel wird für die gleiche Aufgabe ein Funktionsobjekt verwendet.

Beispiel 1: Verwendung eines Lambda-Ausdrucks

In diesem Beispiel wird eine Lambda-Funktion an die for_each-Funktion übergeben. Lambda druckt ein Ergebnis, das besagt, ob jedes Element in einem vector -Objekt ist, gerade oder ungerade.

Code

// even_lambda.cpp
// compile with: cl /EHsc /nologo /W4 /MTd
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main()
{
   // Create a vector object that contains 9 elements.
   vector<int> v;
   for (int i = 1; i < 10; ++i) {
      v.push_back(i);
   }

   // Count the number of even numbers in the vector by
   // using the for_each function and a lambda.
   int evenCount = 0;
   for_each(v.begin(), v.end(), [&evenCount] (int n) {
      cout << n;
      if (n % 2 == 0) {
         cout << " is even " << endl;
         ++evenCount;
      } else {
         cout << " is odd " << endl;
      }
   });

   // Print the count of even numbers to the console.
   cout << "There are " << evenCount
        << " even numbers in the vector." << endl;
}
1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
There are 4 even numbers in the vector.

Kommentare

Im Beispiel ist das dritte Argument für die for_each-Funktion eine Lambda-Funktion. Mit dem [&evenCount]-Teil wird die Erfassungsklausel des Ausdrucks angegeben. Mit (int n) wird die Parameterliste und mit dem Rest der Text des Ausdrucks angegeben.

Beispiel 2: Verwendung eines Funktionsobjekts

Manchmal wäre die Ausweitung eines Lambdas über den Umfang des vorherigen Beispiels hinaus zu hinderlich. Im nächsten Beispiel wird ein Funktionsobjekt anstelle einer Lambda-Funktion zusammen mit der for_each-Funktion verwendet, um dieselben Ergebnisse wie In Beispiel 1 zu erzeugen. In beiden Beispielen wird die Anzahl gerader Zahlen in einem vector-Objekt gespeichert. Um den Zustand des Vorgangs beizubehalten, wird die FunctorClass-Variable von der m_evenCount-Klasse mithilfe eines Verweises als Membervariable gespeichert. Zum Ausführen des Vorgangs FunctorClass implementiert der Funktionsaufrufoperator Operator( ). Der Microsoft C++-Compiler generiert Code, der in Größe und Leistung mit dem Lambda-Code in Beispiel 1 vergleichbar ist. Bei einem grundlegenden Problem, wie dem in diesem Artikel, ist der einfachere Lambda-Entwurf wahrscheinlich besser geeignet, als der Funktionsobjektentwurf. Wenn Sie allerdings der Meinung sind, die Funktionalität erfordere zukünftig möglicherweise beträchtliche Erweiterungen, verwenden Sie einen Funktionsobjektentwurf. Damit ist die Codeverwaltung einfacher.

Weitere Informationen zum Operator() finden Sie unter Funktionsaufruf. Weitere Informationen zur for_each-Funktion finden Sie unter for_each.

Code

// even_functor.cpp
// compile with: /EHsc
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

class FunctorClass
{
public:
    // The required constructor for this example.
    explicit FunctorClass(int& evenCount)
        : m_evenCount(evenCount) { }

    // The function-call operator prints whether the number is
    // even or odd. If the number is even, this method updates
    // the counter.
    void operator()(int n) const {
        cout << n;

        if (n % 2 == 0) {
            cout << " is even " << endl;
            ++m_evenCount;
        } else {
            cout << " is odd " << endl;
        }
    }

private:
    // Default assignment operator to silence warning C4512.
    FunctorClass& operator=(const FunctorClass&);

    int& m_evenCount; // the number of even variables in the vector.
};

int main()
{
    // Create a vector object that contains 9 elements.
    vector<int> v;
    for (int i = 1; i < 10; ++i) {
        v.push_back(i);
    }

    // Count the number of even numbers in the vector by
    // using the for_each function and a function object.
    int evenCount = 0;
    for_each(v.begin(), v.end(), FunctorClass(evenCount));

    // Print the count of even numbers to the console.
    cout << "There are " << evenCount
        << " even numbers in the vector." << endl;
}
1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
There are 4 even numbers in the vector.

Siehe auch

Lambda-Ausdrücke
Beispiele für Lambdaausdrücke
generate
generate_n
for_each
Ausnahmespezifikationen (throw)
Compilerwarnung (Ebene 1) C4297
Microsoft-spezifische Modifizierer