Лямбда
Лямбда без захвата
Я предполагаю, что у вас есть опыт работы с лямбдами из C #, поэтому мы рассмотрим синтаксис, принятый в C ++. Все фрагменты кода из одного и того же файла в одном и том же примере.
Образец: LambdaSample \ LambdaSample.cpp
|
1
2
3
4
5
6
7
8
|
// Create a lambda-expression closure.
auto lm1 = []()
{
wcout << L»No capture, parameterless lambda.»
};
// Invoke the lambda.
lm1();
|
Лямбда с параметрами
|
1
2
3
4
5
6
7
|
// Create a lambda closure with parameters.
auto lm2 = [](int a, int b)
{
wcout << a << L» + » << b << » = » << (a + b) << endl;
};
lm2(3,4);
|
Указание типа возврата лямбды
Конечный тип возврата здесь -> int после спецификации параметра.
|
1
2
3
4
5
6
7
8
|
// Create a lambda closure with a trailing return type.
auto lm3 = [](int a, int b) -> int
{
wcout << a << L» % » << b << » = «;
return a % b;
};
wcout << lm3(7, 5) << endl;
|
Захват внешних переменных
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
int a = 5;
int b = 6;
// Capture by copy all variables that are currently in the scope.
// Note also that we do not need to capture the closure;
// here we simply invoke the anonymous lambda with the
// () after the closing brace.
[=]()
{
wcout << a << L» + » << b << » = » << (a + b) << endl;
//// It’s illegal to modify a here because we have
//// captured by value and have not specified that
//// this lambda should be treated as mutable.
//a = 10;
}();
[=]() mutable -> void
{
wcout << a << L» + » << b << » = » << (a + b) << endl;
// By marking this lambda as mutable, we can now modify a.
// Since we are capturing by value, the modifications
// will not propagate outside.
a = 10;
}();
wcout << L»The value of a is » << a << L».»
[&]()
{
wcout << a << L» + » << b << » = » << (a + b) << endl;
// By capturing by reference, we now do not need
// to mark this as mutable.
// Because it is a reference, though, changes now
// propagate out.
a = 10;
}();
wcout << L»The value of a is » << a << L».»
// Here we specify explicitly that we are capturing a by
// value and b as a reference.
[a,&b]()
{
b = 12;
wcout << a << L» + » << b << » = » << (a + b) << endl;
}();
// Here we specify explicitly that we are capturing b as
// a reference and that all other captures should be by
// value.
[=,&b]()
{
b = 15;
wcout << a << L» + » << b << » = » << (a + b) << endl;
}();
// Here we specify explicitly that we are capturing a by
// value and that all other captures should be by reference.
[&,a]()
{
b = 18;
wcout << a << L» + » << b << » = » << (a + b) << endl;
}();
|
Лямбды в функциях класса
Когда вы используете лямбду в функции члена класса, вы не можете использовать захват по умолчанию по ссылке. Это потому, что лямбда будет снабжена указателем this, и его необходимо скопировать. Кроме того, при работе с умными указателями с подсчетом ссылок часто встречаются проблемы с лямбдами, содержащими ссылку на класс. Обычно вы никогда не вернетесь к нулевому количеству ссылок, что приведет к утечке памяти в вашей программе.
Вывод
Если вы знакомы с лямбда-выражениями в C #, то вам не составит труда привыкнуть к синтаксису в C ++. В следующей статье мы рассмотрим стандартную библиотеку C ++.
Этот урок представляет собой главу из C ++ Succinctly , бесплатной книги от команды Syncfusion .