Przykłady wyrażeń lambda

W tym artykule przedstawiono sposób stosowania wyrażeń lambda w programach. Aby zapoznać się z omówieniem wyrażeń lambda, zobacz Wyrażenia lambda. Aby uzyskać więcej informacji na temat struktury wyrażenia lambda, zobacz Składnia wyrażeń lambda.

Deklarowanie wyrażeń lambda

Przykład 1

Ponieważ wyrażenie lambda jest wpisywane, można przypisać je do zmiennej auto lub do function obiektu, jak pokazano poniżej:

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

W przykładzie są generowane następujące dane wyjściowe:

5
7

Uwagi

Aby uzyskać więcej informacji, zobacz auto, function Klasa i Wywołanie funkcji.

Mimo że wyrażenia lambda są najczęściej deklarowane w treści funkcji, można zadeklarować je w dowolnym miejscu, w którym można zainicjować zmienną.

Przykład 2

Kompilator języka Microsoft C++ wiąże wyrażenie lambda ze przechwyconymi zmiennymi, gdy wyrażenie jest zadeklarowane zamiast w przypadku wywoływania wyrażenia. W poniższym przykładzie pokazano wyrażenie lambda, które przechwytuje zmienną i lokalną według wartości i zmiennej j lokalnej według odwołania. Ponieważ wyrażenie lambda przechwytuje i według wartości, ponowne przypisanie i w dalszej części programu nie ma wpływu na wynik wyrażenia. Jednak ze względu na to, że wyrażenie lambda przechwytuje j przy użyciu odwołania, ponowne przypisanie j elementu wpływa na wynik wyrażenia.

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

W przykładzie są generowane następujące dane wyjściowe:

47

[W tym artykule]

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 biblioteki standardowej języka C++, takich jak find_if.

Przykład 1

W tym przykładzie zadeklarowano wyrażenie lambda, które zwraca sumę dwóch liczb całkowitych i wywołuje wyrażenie natychmiast z argumentami 5 i 4:

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

W przykładzie są generowane następujące dane wyjściowe:

9

Przykład 2

W tym przykładzie wyrażenie lambda jest przekazywaniem wyrażenia lambda jako argumentu find_if do funkcji. Wyrażenie lambda zwraca true wartość , jeśli jego parametr jest liczbą parzystą.

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

W przykładzie są generowane następujące dane wyjściowe:

The first even number in the list is 42.

Uwagi

Aby uzyskać więcej informacji na temat find_if funkcji, zobacz find_if. Aby uzyskać więcej informacji na temat funkcji biblioteki standardowej języka C++ wykonujących typowe algorytmy, zobacz <algorithm>.

[W tym artykule]

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.

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

W przykładzie są generowane następujące dane wyjściowe:

13

Uwagi

W tym przykładzie [](int y) { return y * 2; } jest zagnieżdżone wyrażenie lambda.

[W tym artykule]

Funkcje lambda wyższego rzędu

Przykład

Wiele języków programowania obsługuje koncepcję funkcji wyższej kolejności. Funkcja wyższej kolejności to wyrażenie lambda, które przyjmuje inne wyrażenie lambda jako argument lub zwraca wyrażenie lambda. Możesz użyć function klasy , aby umożliwić wyrażenie lambda języka C++ zachowywać się jak funkcja wyższej kolejności. W poniższym przykładzie pokazano wyrażenie lambda zwracające obiekt i wyrażenie lambda, które function przyjmuje function obiekt jako argument.

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

W przykładzie są generowane następujące dane wyjściowe:

30

[W tym artykule]

Używanie wyrażenia lambda w funkcji

Przykład

Wyrażenia lambda można używać w treści funkcji. Wyrażenie lambda może uzyskać dostęp do dowolnej funkcji lub elementu członkowskiego danych, do którego może uzyskać dostęp otaczającej funkcji. Wskaźnik można jawnie lub niejawnie przechwycić this , aby zapewnić dostęp do funkcji i składowych danych otaczającej klasy. Program Visual Studio 2017 w wersji 15.3 lub nowszej (dostępny z /std:c++17 i nowszymi): przechwyć this według wartości ([*this]), gdy lambda będzie używana w operacjach asynchronicznych lub równoległych, w których kod może zostać wykonany po tym, jak oryginalny obiekt wykracza poza zakres.

Wskaźnik można jawnie użyć this w funkcji, jak pokazano poniżej:

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

Wskaźnik można również przechwycić 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 przedstawiono klasę Scale , która hermetyzuje wartość skalowania.

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

W przykładzie są generowane następujące dane wyjściowe:

3
6
9
12

Uwagi

Funkcja ApplyScale używa wyrażenia lambda do drukowania produktu wartości skalowania i każdego elementu w vector obiekcie. Wyrażenie lambda niejawnie przechwytuje this , aby umożliwić mu dostęp do _scale elementu członkowskiego.

[W tym artykule]

Używanie 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 przedstawiono negate_all funkcje i print_all . Funkcja negate_all stosuje jednoargumentowy operator- do każdego elementu w vector obiekcie. Funkcja print_all drukuje każdy element w vector obiekcie w konsoli programu .

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

W przykładzie są generowane następujące dane wyjściowe:

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

Uwagi

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

[W tym artykule]

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 for_each funkcji i wyrażenia lambda, aby wypełnić vector obiekt wartościami innego. Używa try/catch bloku do obsługi nieprawidłowego dostępu do pierwszego wektora.

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

W przykładzie są generowane następujące dane wyjściowe:

Caught 'invalid vector<T> subscript'.

Uwagi

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

[W tym artykule]

Używanie wyrażeń lambda z typami zarządzanymi (C++/CLI)

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ą niezarządzaną zmienną ch według wartości i przyjmuje System.String obiekt jako jego parametr.

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

W przykładzie są generowane następujące dane wyjściowe:

Hello!

Uwagi

Można również używać wyrażeń lambda z biblioteką STL/CLR. Aby uzyskać więcej informacji, zobacz STL/CLR Library Reference (Dokumentacja biblioteki STL/CLR).

Ważne

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

[W tym artykule]

Zobacz też

Wyrażenia lambda
Składnia wyrażenia lambda
auto
function Klasa
find_if
<algorithm>
Wywołanie funkcji
Szablony
Obsługa wyjątków
Dokumentacja biblioteki STL/CLR