Лямбда
Лямбда без захвата
Я предполагаю, что у вас есть опыт работы с лямбдами из 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 .