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ż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
auto — słowo kluczowe (typ odliczenia)
Obsługa wyjątków w języku Visual C++