Beispiele für Lambdaausdrücke

Dieser Artikel zeigt, wie Lambdaausdrücke in Ihren Programmen zu verwenden sind. Eine Übersicht über die Lambdaausdrücke finden Sie unter Lambdaausdrücke. Weitere Informationen zur Struktur eines Lambdaausdrucks finden Sie unter Lambdaausdruckssyntax.

Deklarieren von Lambdaausdrücken

Beispiel 1

Da ein Lambdaausdruck typisiert ist, können Sie ihn einer auto-Variablen oder einem function-Objekt zuweisen, wie im folgenden Beispiel gezeigt:

// declaring_lambda_expressions1.cpp
// compile with: /EHsc /W4
#include <functional>
#include <iostream>

int main()
{
    using namespace std;

    // Assign the lambda expression that adds two numbers to an auto variable.
    auto f1 = [](int x, int y) { return x + y; };

    cout << f1(2, 3) << endl;

    // Assign the same lambda expression to a function object.
    function<int(int, int)> f2 = [](int x, int y) { return x + y; };

    cout << f2(3, 4) << endl;
}

Das Beispiel generiert die folgende Ausgabe:

5
7

Hinweise

Weitere Informationen finden Sie unter auto, function Klasse und Funktionsaufruf.

Obwohl Lambdaausdrücke am häufigsten im Text einer Funktion deklariert werden, können Sie sie überall da deklarieren, wo Sie eine Variable initialisieren können.

Beispiel 2

Der Compiler für Microsoft C++ bindet einen Lambdaausdruck an die erfassten Variablen, wenn der Ausdruck deklariert wird, anstatt wenn der Ausdruck aufgerufen wird. Das folgende Beispiel zeigt einen Lambdaausdruck, der die lokale Variable i nach Wert erfasst und die lokale Variable j nach Verweis. Da der Lambda-Ausdruck i als Wert erfasst, wirkt sich die Neuzuweisung von i später im Programm nicht auf das Ergebnis des Ausdrucks aus. Da der Lambdaausdruck j jedoch als Verweis erfasst, wirkt sich die erneute Zuweisung von j auf das Ergebnis des Ausdrucks aus.

// declaring_lambda_expressions2.cpp
// compile with: /EHsc /W4
#include <functional>
#include <iostream>

int main()
{
   using namespace std;

   int i = 3;
   int j = 5;

   // The following lambda expression captures i by value and
   // j by reference.
   function<int (void)> f = [i, &j] { return i + j; };

   // Change the values of i and j.
   i = 22;
   j = 44;

   // Call f and print its result.
   cout << f() << endl;
}

Das Beispiel generiert die folgende Ausgabe:

47

[In diesem Artikel]

Aufrufen von Lambdaausdrücken

Sie können einen Lambdaausdruck sofort aufrufen, wie im nächsten Codeausschnitt gezeigt wird. Der zweite Ausschnitt zeigt, wie ein Lambda als Argument an Standardbibliotheks-Algorithmen von C++ übergeben wird, wie z. B. an find_if.

Beispiel 1

Im folgenden Beispiel wird ein Lambdaausdruck deklariert, der die Summe von zwei ganze Zahlen zurückgibt und den Ausdruck sofort mit den Argumenten 5 und 4 aufruft:

// calling_lambda_expressions1.cpp
// compile with: /EHsc
#include <iostream>

int main()
{
   using namespace std;
   int n = [] (int x, int y) { return x + y; }(5, 4);
   cout << n << endl;
}

Das Beispiel generiert die folgende Ausgabe:

9

Beispiel 2

Im folgenden Beispiel wird ein Lambdaausdruck als Argument an die find_if-Funktion übergeben. Der Lambdaausdruck gibt true zurück, wenn sein Parameter eine gerade Zahl ist.

// calling_lambda_expressions2.cpp
// compile with: /EHsc /W4
#include <list>
#include <algorithm>
#include <iostream>

int main()
{
    using namespace std;

    // Create a list of integers with a few initial elements.
    list<int> numbers;
    numbers.push_back(13);
    numbers.push_back(17);
    numbers.push_back(42);
    numbers.push_back(46);
    numbers.push_back(99);

    // Use the find_if function and a lambda expression to find the
    // first even number in the list.
    const list<int>::const_iterator result =
        find_if(numbers.begin(), numbers.end(),[](int n) { return (n % 2) == 0; });

    // Print the result.
    if (result != numbers.end()) {
        cout << "The first even number in the list is " << *result << "." << endl;
    } else {
        cout << "The list contains no even numbers." << endl;
    }
}

Das Beispiel generiert die folgende Ausgabe:

The first even number in the list is 42.

Hinweise

Weitere Informationen zur find_if-Funktion finden Sie unter find_if. Weitere Informationen zu den Standardbibliotheksfunktionen bei C++, die allgemeine Algorithmen ausführen, finden Sie unter <algorithm>.

[In diesem Artikel]

Schachteln von Lambdaausdrücken

Beispiel

Sie können einen Lambda-Ausdruck innerhalb eines anderen schachteln, wie in diesem Beispiel gezeigt wird. Der innere Lambdaausdruck multipliziert sein Argument mit 2 und gibt das Ergebnis zurück. Der äußere Lambdaausdruck ruft den inneren Lambdaausdruck mit seinem Argument auf und fügt dem Ergebnis 3 hinzu.

// nesting_lambda_expressions.cpp
// compile with: /EHsc /W4
#include <iostream>

int main()
{
    using namespace std;

    // The following lambda expression contains a nested lambda
    // expression.
    int timestwoplusthree = [](int x) { return [](int y) { return y * 2; }(x) + 3; }(5);

    // Print the result.
    cout << timestwoplusthree << endl;
}

Das Beispiel generiert die folgende Ausgabe:

13

Hinweise

In diesem Beispiel ist [](int y) { return y * 2; } der geschachtelte Lambdaausdruck.

[In diesem Artikel]

Lambdafunktionen höherer Ordnung

Beispiel

Viele Programmiersprachen unterstützen das Konzept einer Funktion höherer Ordnung. Eine Funktion höherer Ordnung ist ein Lambda-Ausdruck, der einen anderen Lambda-Ausdruck als Argument akzeptiert oder einen Lambda-Ausdruck zurückgibt. Sie können die function-Klasse verwenden, damit sich ein C++-Lambdaausdruck wie eine Funktion höherer Ordnung verhält. Das folgende Beispiel zeigt einen Lambdaausdruck, der ein function-Objekt zurückgibt, und einen Lambdaausdruck, der ein function-Objekt als sein Argument akzeptiert.

// higher_order_lambda_expression.cpp
// compile with: /EHsc /W4
#include <iostream>
#include <functional>

int main()
{
    using namespace std;

    // The following code declares a lambda expression that returns
    // another lambda expression that adds two numbers.
    // The returned lambda expression captures parameter x by value.
    auto addtwointegers = [](int x) -> function<int(int)> {
        return [=](int y) { return x + y; };
    };

    // The following code declares a lambda expression that takes another
    // lambda expression as its argument.
    // The lambda expression applies the argument z to the function f
    // and multiplies by 2.
    auto higherorder = [](const function<int(int)>& f, int z) {
        return f(z) * 2;
    };

    // Call the lambda expression that is bound to higherorder.
    auto answer = higherorder(addtwointegers(7), 8);

    // Print the result, which is (7+8)*2.
    cout << answer << endl;
}

Das Beispiel generiert die folgende Ausgabe:

30

[In diesem Artikel]

Verwenden eines Lambdaausdrucks in einer Funktion

Beispiel

Sie können Lambda-Ausdrücke im Text einer Funktion verwenden. Der Lambdaausdruck kann auf alle Funktionen oder Datenmember zugreifen, auf die die einschließende Funktion zugreifen kann. Sie können den this-Zeiger explizit oder implizit erfassen, um Zugriff auf die Funktionen und Datenelemente der einschließenden Klasse zu gewähren. Visual Studio 2017, Version 15.3 und höher (verfügbar mit /std:c++17 und höher): Erfassen Sie this nach Wert ([*this]), wenn der Lambdaausdruck in asynchronen oder parallelen Vorgängen verwendet wird, bei denen der Code ausgeführt werden kann, nachdem das ursprüngliche Objekt nicht mehr gültig ist.

Sie können den this-Zeiger explizit in einer Funktion verwenden, wie hier gezeigt wird:

// capture "this" by reference
void ApplyScale(const vector<int>& v) const
{
   for_each(v.begin(), v.end(),
      [this](int n) { cout << n * _scale << endl; });
}

// capture "this" by value (Visual Studio 2017 version 15.3 and later)
void ApplyScale2(const vector<int>& v) const
{
   for_each(v.begin(), v.end(),
      [*this](int n) { cout << n * _scale << endl; });
}

Sie können den this-Zeiger auch implizit erfassen:

void ApplyScale(const vector<int>& v) const
{
   for_each(v.begin(), v.end(),
      [=](int n) { cout << n * _scale << endl; });
}

Das folgende Beispiel zeigt die Scale-Klasse, die einen Skalierungswert kapselt.

// function_lambda_expression.cpp
// compile with: /EHsc /W4
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

class Scale
{
public:
    // The constructor.
    explicit Scale(int scale) : _scale(scale) {}

    // Prints the product of each element in a vector object
    // and the scale value to the console.
    void ApplyScale(const vector<int>& v) const
    {
        for_each(v.begin(), v.end(), [=](int n) { cout << n * _scale << endl; });
    }

private:
    int _scale;
};

int main()
{
    vector<int> values;
    values.push_back(1);
    values.push_back(2);
    values.push_back(3);
    values.push_back(4);

    // Create a Scale object that scales elements by 3 and apply
    // it to the vector object. doesn't modify the vector.
    Scale s(3);
    s.ApplyScale(values);
}

Das Beispiel generiert die folgende Ausgabe:

3
6
9
12

Hinweise

Die ApplyScale-Funktion verwendet einen Lambdaausdruck, um das Produkt des Skalierungswerts und eines jeden Elements in einem vector-Objekt auszugeben. Der Lambdaausdruck erfasst den this-Zeiger implizit, sodass er auf den _scale-Member zugreifen kann.

[In diesem Artikel]

Verwenden von Lambdaausdrücken mit Vorlagen

Beispiel

Da Lambdaausdrücke typisiert sind, können Sie sie mit C++-Vorlagen verwenden. Im folgenden Beispiel werden die Funktionen negate_all und print_all dargestellt. Die negate_all-Funktion wendet den unären Operator operator- auf jedes Element im vector-Objekt an. Die print_all-Funktion gibt jedes Element im vector-Objekt auf der Konsole aus.

// template_lambda_expression.cpp
// compile with: /EHsc
#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

// Negates each element in the vector object. Assumes signed data type.
template <typename T>
void negate_all(vector<T>& v)
{
    for_each(v.begin(), v.end(), [](T& n) { n = -n; });
}

// Prints to the console each element in the vector object.
template <typename T>
void print_all(const vector<T>& v)
{
    for_each(v.begin(), v.end(), [](const T& n) { cout << n << endl; });
}

int main()
{
    // Create a vector of signed integers with a few elements.
    vector<int> v;
    v.push_back(34);
    v.push_back(-43);
    v.push_back(56);

    print_all(v);
    negate_all(v);
    cout << "After negate_all():" << endl;
    print_all(v);
}

Das Beispiel generiert die folgende Ausgabe:

34
-43
56
After negate_all():
-34
43
-56

Hinweise

Weitere Informationen zu C++-Vorlagen finden Sie unter Vorlagen.

[In diesem Artikel]

Behandeln von Ausnahmen

Beispiel

Der Text eines Lambda-Ausdrucks folgt den Regeln für die strukturierte Ausnahmebehandlung (SEH) und die C++-Ausnahmebehandlung. Sie können eine ausgelöste Ausnahme im Text eines Lambda-Ausdrucks behandeln oder die Ausnahmebehandlung auf den umschließenden Gültigkeitsbereich verzögern. Im folgenden Beispiel wird die for_each-Funktion und ein Lambdaausdruck verwendet, um ein vector-Objekt mit den Werten eines anderen Objekts zu füllen. Es wird ein try/catch-Block verwendet, um ungültigen Zugriff auf den ersten Vektor zu behandeln.

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

int main()
{
    // Create a vector that contains 3 elements.
    vector<int> elements(3);

    // Create another vector that contains index values.
    vector<int> indices(3);
    indices[0] = 0;
    indices[-1] = 1; // This is not a valid subscript. It will trigger an exception.
    indices[2] = 2;

    // Use the values from the vector of index values to
    // fill the elements vector. This example uses a
    // try/catch block to handle invalid access to the
    // elements vector.
    try
    {
        for_each(indices.begin(), indices.end(), [&](int index) {
            elements.at(index) = index;
        });
    }
    catch (const out_of_range& e)
    {
        cerr << "Caught '" << e.what() << "'." << endl;
    };
}

Das Beispiel generiert die folgende Ausgabe:

Caught 'invalid vector<T> subscript'.

Hinweise

Weitere Informationen zur Behandlung von Ausnahmen finden Sie unter Ausnahmebehandlung.

[In diesem Artikel]

Verwenden von Lambdaausdrücken mit verwalteten Typen (C++/CLI)

Beispiel

Die Erfassungsklausel eines Lambdaausdrucks darf keine Variable mit einem verwalteten Typ enthalten. Sie können jedoch ein Argument mit einem verwalteten Typ an die Parameterliste eines Lambdaausdrucks übergeben. Das folgende Beispiel enthält einen Lambda-Ausdruck, der die lokale nicht verwaltete ch-Variable nach ihrem Wert erfasst und ein System.String-Objekt als Parameter akzeptiert.

// managed_lambda_expression.cpp
// compile with: /clr
using namespace System;

int main()
{
    char ch = '!'; // a local unmanaged variable

    // The following lambda expression captures local variables
    // by value and takes a managed String object as its parameter.
    [=](String ^s) {
        Console::WriteLine(s + Convert::ToChar(ch));
    }("Hello");
}

Das Beispiel generiert die folgende Ausgabe:

Hello!

Hinweise

Sie können Lambdaausdrücke auch mit der STL/CLR-Bibliothek verwenden. Weitere Informationen finden Sie unter Referenz zur STL/CLR-Bibliothek.

Wichtig

Lambdas werden in diesen verwalteten Entitäten der Common Language Runtime (CLR) nicht unterstützt: ref class, ref struct, value class und value struct.

[In diesem Artikel]

Siehe auch

Lambda-Ausdrücke
Lambdaausdruckssyntax
auto
function-Klasse
find_if
<algorithm>
Funktionsaufruf
Vorlagen
Ausnahmebehandlung
Referenz zur STL/CLR-Bibliothek