Udostępnij za pośrednictwem


Przykłady wyrażeń lambda

W tym artykule przedstawiono sposób stosowania wyrażeń lambda w programach.Aby uzyskać informacje na temat wyrażeń lambda, zobacz Wyrażenia lambda w języku C++.Aby uzyskać więcej informacji na temat struktury wyrażenia lambda, zobacz Składnia wyrażenia lambda.

W tym artykule

Deklarowanie wyrażeń lambda

Wywoływanie wyrażeń lambda

Zagnieżdżanie wyrażeń lambda

Funkcje lambda wyższego rzędu

Użycie wyrażenia lambda w metodzie

Użycie wyrażeń lambda z szablonami

Obsługa wyjątków

Użycie wyrażeń lambda z typami zarządzanymi

Deklarowanie wyrażeń lambda

Przykład 1

Ponieważ wyrażenie lambda ma typ, można je przypisać do zmiennej auto lub do obiektu function, jak pokazano tutaj:

Kod

// 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;
}

Dane wyjściowe

  

Uwagi

Aby uzyskać więcej informacji, zobacz auto — słowo kluczowe (typ odliczenia), function — Klasa i Wywołanie funkcji (C++).

Chociaż wyrażenia lambda najczęściej są deklarowane w treści metody lub funkcji, można je zadeklarować gdziekolwiek tam, gdzie można zainicjować zmienną.

Przykład 2

Kompilator języka Visual C++ wiąże wyrażenie lambda do swoich zmiennych przechwyconych, gdy wyrażenie jest zadeklarowane, a nie wtedy, gdy wyrażenie jest wywoływane.Poniższy przykład pokazuje wyrażenie lambda, które przechwytuje zmienną lokalną i przez wartość i zmienną lokalną j przez odwołanie.Ponieważ wyrażenie lambda przechwytuje i przez wartość, ponowne przypisanie i później w programie nie wpływa na wynik wyrażenia.Jednak, ponieważ wyrażenie lambda przechwytuje j przez odwołanie, ponowne przypisanie j nie wpływa na wynik wyrażenia.

Kod

// 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;
}

Dane wyjściowe

  

[Przejdź do góry]

Wywoływanie wyrażeń lambda

Wyrażenie lambda można wywołać natychmiast, jak pokazano w następnym fragmencie kodu programu.Drugi fragment kodu pokazuje, jak przekazać lambda jako argument do algorytmów standardowej biblioteki szablonów (STL), takich jak find_if.

Przykład 1

Ten przykład deklaruje wyrażenie lambda, które zwraca sumę dwóch liczb całkowitych i wywołuje wyrażenie bezpośrednio z argumentami 5 i 4:

Kod

// 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;
}

Dane wyjściowe

  

Przykład 2

Ten przykład przekazuje wyrażenie lambda jako argument do funkcji find_if.Wyrażenie lambda zwraca true, jeśli jego parametr jest liczbą parzystą.

Kod

// 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;
    }
}

Dane wyjściowe

  

Uwagi

Aby uzyskać więcej informacji dotyczących funkcji find_if, zobacz find_if.Aby uzyskać więcej informacji na temat funkcji STL, wykonujących typowe algorytmy, zobacz <algorithm>.

[Przejdź do góry]

Zagnieżdżanie wyrażeń lambda

Przykład

Można zagnieżdżać wyrażenia lambda wewnątrz siebie, jak pokazano w poniższym przykładzie.Wewnętrzne wyrażenie lambda mnoży swój argument przez 2 i zwraca wynik.Wyrażenie zewnętrzne lambda wywołuje wyrażenie wewnętrzne lambda z jego argumentem i dodaje do wyniku 3.

Kod

// 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;
}

Dane wyjściowe

  

Uwagi

W tym przykładzie wartość [](int y) { return y * 2; } jest zagnieżdżonym wyrażeniem lambda.

[Przejdź do góry]

Funkcje lambda wyższego rzędu

Przykład

Wiele języków programowania wspiera koncepcję funkcji wyższego rzędu. Funkcja wyższego rzędu jest wyrażeniem lambda, które pobiera inne wyrażenie lambda jako argument, lub które zwraca wyrażenie lambda.Można użyć klasy function, aby umożliwić wyrażeniu lambda C++ zachowywanie się jak funkcja wyższego rzędu.W poniższym przykładzie pokazano wyrażenie lambda, która zwraca obiekt function, i wyrażenie lambda, które przyjmuje obiekt function jako argument.

Kod

// 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;
}

Dane wyjściowe

  

[Przejdź do góry]

Użycie wyrażenia lambda w metodzie

Przykład

Można użyć wyrażeń lambda w strukturze metody.Wyrażenie lambda może uzyskać dostęp do którejkolwiek metody lub któregokolwiek elementu członkowskiego danych, do których dostęp ma otaczająca metoda.Można jawnie lub niejawnie przechwycić wskaźnik this, aby uzyskać dostęp do metod i elementów członkowskich danych otaczającej klasy.

Można jawnie użyć wskaźnika this w metodzie, jak pokazano poniżej:

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

Istnieje również możliwość przechwytywania wskaźnika this niejawnie:

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

W poniższym przykładzie pokazano klasę Scale, która hermetyzuje wartość skali.

// method_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. Does not modify the vector.
    Scale s(3);
    s.ApplyScale(values);
}

Dane wyjściowe

  

Uwagi

Metoda ApplyScale używa wyrażenia lambda do wyświetlenia wyniku wartości skali i każdego elementu w obiekcie vector.Wyrażenie lambda niejawnie przechwytuje this, więc może uzyskać dostęp do elementu członkowskiego _scale.

[Przejdź do góry]

Użycie wyrażeń lambda z szablonami

Przykład

Ponieważ wyrażenia lambda mają typ, można ich użyć z szablonami języka C++.W poniższym przykładzie pokazano funkcje negate_all i print_all.Funkcja negate_all stosuje jednoargumentowy operator- do każdego elementu w obiekcie vector.Funkcja print_all wyświetla w konsoli każdy element w obiekcie vector.

Kod

// 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);
}

Dane wyjściowe

  

Uwagi

Aby uzyskać więcej informacji na temat szablonów języka C++, zobacz Szablony.

[Przejdź do góry]

Obsługa wyjątków

Przykład

Treść wyrażenia lambda kieruje się regułami dla obsługi wyjątków strukturalnych (SEH) i obsługi wyjątków C++.Można obsługiwać zgłoszony wyjątek w ciele wyrażenia lambda lub odroczyć obsługę wyjątków do zasięgu otaczającego.W poniższym przykładzie użyto funkcji for_each i wyrażenia lambda do wypełnienia obiektu vector wartością innego.Używa on bloku try/catch do obsługi nieprawidłowego dostępu do pierwszego wektora.

Kod

// 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;
    };
}

Dane wyjściowe

  

Uwagi

Aby uzyskać więcej informacji na temat obsługi wyjątków, zobacz Obsługa wyjątków w języku Visual C++.

[Przejdź do góry]

Użycie wyrażeń lambda z typami zarządzanymi

Przykład

Klauzula przechwytywania wyrażenia lambda nie może zawierać zmiennej, która ma typ zarządzany.Jednak do listy parametrów wyrażenia lambda można przekazać argument, który ma typ zarządzany.Poniższy przykład zawiera wyrażenie lambda, które przechwytuje lokalną zmienną niezarządzaną ch przez wartość i przyjmuje obiekt String jako parametr.

Kod

// 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");
}

Dane wyjściowe

  

Uwagi

Można również używać wyrażeń lambda z biblioteką STL/CLR.Aby uzyskać więcej informacji, zobacz Odwołanie do biblioteki STL/CLR.

Ważna uwagaWażne

Wyrażenia lambda nie są obsługiwane w tych jednostkach zarządzanych środowiska uruchomieniowego języka wspólnego (CLR): ref class, ref struct, value class, value struct.

[Przejdź do góry]

Zobacz też

Informacje

Wyrażenia lambda w języku C++

Składnia wyrażenia lambda

auto — słowo kluczowe (typ odliczenia)

function — Klasa

find_if

<algorithm>

Wywołanie funkcji (C++)

Obsługa wyjątków w języku Visual C++

Inne zasoby

Szablony

Odwołanie do biblioteki STL/CLR