Одно из лучших объяснений lambda expression
дано автором C ++ Bjarne Stroustrup в его книге ***The C++ Programming Language***
глава 11 ( ISBN-13: 978-0321563842 ):
What is a lambda expression?
A лямбда-выражение , иногда также называемое функцией лямбда или (строго говоря, но разговорно) как лямбда , является упрощенным обозначением для определения и использования анонимного функционального объекта. Вместо определения именованного класса с помощью оператора (), позже создающего объект этого класса и, наконец, вызывающего его, мы можем использовать сокращенное обозначение.
blockquote>
When would I use one?
Это особенно полезно, когда мы хотим передать операцию в качестве аргумента алгоритму. В контексте графических пользовательских интерфейсов (и в других местах) такие операции часто называют обратными вызовами .
blockquote>
What class of problem do they solve that wasn't possible prior to their introduction?
Здесь Я предполагаю, что каждое действие, выполняемое с помощью лямбда-выражения, может быть разрешено без них, но с гораздо большим количеством кода и гораздо большей сложностью. Лямбда-выражение - это способ оптимизации вашего кода и способ сделать его более привлекательным. Как печально Stroustup:
эффективные способы оптимизации
blockquote>
Some examples
через lambda выражение
void print_modulo(const vector
& v, ostream& os, int m) // output v[i] to os if v[i]%m==0 { for_each(begin(v),end(v), [&os,m](int x) { if (x%m==0) os << x << '\n'; }); } или через функцию
class Modulo_print { ostream& os; // members to hold the capture list int m; public: Modulo_print(ostream& s, int mm) :os(s), m(mm) {} void operator()(int x) const { if (x%m==0) os << x << '\n'; } };
или даже
void print_modulo(const vector
& v, ostream& os, int m) // output v[i] to os if v[i]%m==0 { class Modulo_print { ostream& os; // members to hold the capture list int m; public: Modulo_print (ostream& s, int mm) :os(s), m(mm) {} void operator()(int x) const { if (x%m==0) os << x << '\n'; } }; for_each(begin(v),end(v),Modulo_print{os,m}); } , если вам нужно u, можно назвать
lambda expression
, как показано ниже:void print_modulo(const vector
& v, ostream& os, int m) // output v[i] to os if v[i]%m==0 { auto Modulo_print = [&os,m] (int x) { if (x%m==0) os << x << '\n'; }; for_each(begin(v),end(v),Modulo_print); } Или предположим, что еще один простой образец
void TestFunctions::simpleLambda() { bool sensitive = true; std::vector
v = std::vector ({1,33,3,4,5,6,7}); sort(v.begin(),v.end(), [sensitive](int x, int y) { printf("\n%i\n", x < y); return sensitive ? x < y : abs(x) < abs(y); }); printf("sorted"); for_each(v.begin(), v.end(), [](int x) { printf("x - %i;", x); } ); } будет генерировать следующий
0
1
0
1
0
1
0
1
0
1
0 sortedx - 1; x - 3; x - 4; x - 5; x - 6; x - 7; x - 33;
blockquote>
[]
- это список захвата илиlambda introducer
: еслиlambdas
не требует доступа к своей локальной среде, мы можем его использовать.Цитата из книги:
Первая Характер лямбда-выражения всегда [. Интенсификатор лямбда может принимать различные формы:
• []: пустой список захвата. Это означает, что никакие локальные имена из окружающего контекста не могут использоваться в лямбда-теле. Для таких лямбда-выражений данные получены из аргументов или из нелокальных переменных.
• [& amp;]: неявно захватывать по ссылке. Можно использовать все локальные имена. Доступ ко всем локальным переменным осуществляется по ссылке.
• [=]: неявно фиксировать по значению. Можно использовать все локальные имена. Все имена относятся к копиям локальных переменных, взятых в точке вызова лямбда-выражения.
• [capture-list]: явный захват; Список захвата - это список имен локальных переменных, которые должны быть захвачены (т. е. сохранены в объекте) по ссылке или по значению. Переменные с именами, которым предшествует & amp; записываются по ссылке. Другие переменные фиксируются по значению. Список захвата также может содержать это и имена, за которыми следуют ... как элементы.
• [& amp ;, capture-list]: неявно захватывать по ссылке все локальные переменные с именами, не указанными в списке. Этот список может содержать список захвата. Перечисленным именам не может предшествовать & amp ;. Переменные, названные в списке захвата, записываются по значению.
• [=, capture-list]: неявно захватывать по значению все локальные переменные с именами, не указанными в списке. Список захвата не может содержать этого. Перечисленным именам должно предшествовать & amp ;. Вариаторы, названные в списке захвата, записываются по ссылке.
Обратите внимание, что локальное имя, которому предшествует & amp; всегда фиксируется по ссылке и локальное имя, не указанное с помощью & amp; всегда фиксируется по значению.
blockquote>
Additional
Lambda expression
formatДополнительные ссылки:
- Wiki
- open-std.org , глава 5.1.2