Sdílet prostřednictvím


Příklady výrazů lambda

Tento článek ukazuje, jak můžete použít výrazy lambda v programech.Přehled výrazů lambda naleznete v tématu Výrazy lambda v jazyce C++.Další informace o struktuře výrazu lambda naleznete v tématu Syntaxe výrazu lambda.

V tomto článku

Deklarování výrazů lambda

Volání výrazů lambda

Vnořování výrazů lambda

Lambda funkce vyššího řádu

Použití výrazu lambda v metodě

Použití výrazů lambda se šablonami

Zpracování výjimek

Použití výrazů lambda se spravovanými typy

Deklarování výrazů lambda

Příklad 1

Protože má výraz lambda typ, můžete jej přiřadit k proměnné auto nebo k objektu function, jak je znázorněno zde:

Kód

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

Výstup

  

Poznámky

Další informace naleznete v tématu auto – klíčové slovo (odvození typu), function – třída a Volání funkcí (C++).

Přestože výrazy lambda jsou často deklarovány v těle metody nebo funkce, můžete je deklarovat kdekoli, kde lze inicializovat proměnnou.

Příklad 2

Kompilátor Visual C++ sváže lambda výraz s jeho zachycenými proměnnými při deklaraci výrazu místo při jeho volání.Následující příklad ukazuje výraz lambda, který explicitně zaznamenává místní proměnnou i podle hodnoty a místní proměnnou j podle odkazu.Vzhledem k tomu, že lambda výraz zachytí i podle hodnoty, přeřazení i dále v programu neovlivní výsledek výrazu.Protože však lambda výraz zachytí j podle odkazu, přeřazení j ovlivní výsledek výrazu.

Kód

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

Výstup

  

[Přejděte do horní]

Volání výrazů lambda

Výraz lambda můžete volat ihned, jak je znázorněno v následujícím fragmentu kódu.Druhý fragment kódu ukazuje, jak předat výraz lambda jako argument pro algoritmy knihovny STL, např. find_if.

Příklad 1

Tento příklad deklaruje výraz lambda, který vrací součet dvou celých čísel, a okamžitě volá výraz s argumenty 5 a 4:

Kód

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

Výstup

  

Příklad 2

Tento příklad předává výraz lambda jako argument funkci find_if.Výraz lambda vrací true, je-li jeho parametr sudé číslo.

Kód

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

Výstup

  

Poznámky

Další informace o funkci find_if naleznete v části find_if.Další informace o funkcích STL, které provádějí běžné algoritmy, naleznete v tématu <algorithm>.

[Přejděte do horní]

Vnořování výrazů lambda

Příklad

Výraz lambda můžete vnořit do jiného tak, jak je ukázáno v následujícím příkladu.Vnitřní výraz lambda vynásobí svůj argument 2 a vrátí výsledek.Vnější výraz lambda volá vnitřní výraz lambda s argumentem a k výsledku přičte 3.

Kód

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

Výstup

  

Poznámky

V tomto příkladu je [](int y) { return y * 2; } vnořený výraz lambda.

[Přejděte do horní]

Lambda funkce vyššího řádu

Příklad

Mnoho programovacích jazyků podporuje koncept funkcí vyšší úrovně. Funkce vyššího řádu je výraz lambda, který bere další výraz lambda jako svůj argument nebo který vrací výraz lambda.Pomocí třídy function můžete povolit výrazu lambda v jazyce C++ chovat se jako funkce vyšší úrovně.Následující příklad ukazuje výraz lambda, který vrací objekt function, a výraz lambda, který má jako argument objekt function.

Kód

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

Výstup

  

[Přejděte do horní]

Použití výrazu lambda v metodě

Příklad

Můžete použít výrazy lambda v těle metody.Výraz lambda má přístup k libovolné metodě nebo datovému členu, ke kterému má ohraničující metoda přístup.Můžete explicitně nebo implicitně zachytit ukazatel this a zajistit tak přístup k metodám a datovým členům ohraničující třídy.

Ukazatel this můžete explicitně použít v metodě, jak je uvedeno zde:

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

Ukazatel this můžete také zachytit implicitně:

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

Následující příklad ukazuje třídu Scale, která zapouzdřuje hodnotu měřítka.

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

Výstup

  

Poznámky

Metoda ApplyScale používá výraz lambda k tisku výsledku jednotlivých prvků v objektu vector a hodnotě měřítka.Výraz lambda implicitně zachycuje this tak, aby měl přístup ke členu _scale.

[Přejděte do horní]

Použití výrazů lambda se šablonami

Příklad

Protože výrazy lambda mají typ, můžete je použít s šablonami jazyka C++.Následující příklad ukazuje funkce negate_all a print_all.Funkce negate_all použije unární operator- na každý prvek v objektu vector.Funkce print_all vypíše všechny prvky v objektu vector na konzole.

Kód

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

Výstup

  

Poznámky

Další informace o šablonách jazyka C++ naleznete v tématu Šablony.

[Přejděte do horní]

Zpracování výjimek

Příklad

Tělo výrazu lambda je v souladu s pravidly pro strukturované zpracování výjimek (SEH) i zpracování výjimek jazyka C++.V těle výrazu lambda můžete zpracovat vyvolanou výjimku nebo pozdržet zpracování výjimek pro nadřazený obor.V následujícím příkladu se využívá funkce for_each a výraz lambda pro vyplnění jednoho objektu vector hodnotami druhého.Používá blok try/catch ke zpracování neplatného přístupu k prvnímu vektoru.

Kód

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

Výstup

  

Poznámky

Další informace o zpracování výjimky naleznete v tématu Zpracování výjimek v jazyce Visual C++.

[Přejděte do horní]

Použití výrazů lambda se spravovanými typy

Příklad

Klauzule zachycení výrazu lambda nemůže obsahovat proměnnou se spravovaným typem.Můžete však předat argument se spravovaným typem do seznamu parametrů výrazu lambda.Následující příklad obsahuje výraz lambda, který zachytává místní nespravovanou proměnnou ch podle hodnoty a jako parametr bere objekt String.

Kód

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

Výstup

  

Poznámky

Výrazy lambda můžete použít také s knihovnou STL/CLR.Další informace naleznete v tématu STL/CLR – Referenční dokumentace knihoven.

Důležitá poznámkaDůležité

Výrazy lambda nejsou podporovány následujícími spravovanými entitami modulu CLR: ref class, ref struct, value class a value struct.

[Přejděte do horní]

Viz také

Referenční dokumentace

Výrazy lambda v jazyce C++

Syntaxe výrazu lambda

auto – klíčové slovo (odvození typu)

function – třída

find_if

<algorithm>

Volání funkcí (C++)

Zpracování výjimek v jazyce Visual C++

Další zdroje

Šablony

STL/CLR – Referenční dokumentace knihoven