Синтаксис лямбда-выражения
В этом разделе описывается синтаксис лямбда-выражения.Он предоставляет пример, демонстрирующий структурных элементов лямбда-выражения и как эти элементы относятся к примеру.
Следующая программа использует лямбда-выражения с двумя алгоритмы библиотеки STL: generate_n и for_each.Лямбда-выражение, которое появляется при вызове generate_n функция присваивает элементу vector объекта к сумме предыдущих двух элементов.Лямбда-выражение, которое появляется при вызове for_each функция выводит элемент того же vector объекта на консоль.
// lambda_structure.cpp
// compile with: /EHsc
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
// The number of elements in the vector.
const int elementCount = 9;
int main()
{
// Create a vector object with each element set to 1.
vector<int> v(elementCount, 1);
// These variables hold the previous two elements of the vector.
int x = 1;
int y = 1;
// Assign each element in the vector to the sum of the
// previous two elements.
generate_n(v.begin() + 2, elementCount - 2, [=]() mutable throw() -> int {
// Generate current value.
int n = x + y;
// Update previous two values.
x = y;
y = n;
return n;
});
// Print the contents of the vector.
for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
cout << endl;
// Print the local variables x and y.
// The values of x and y hold their initial values because
// they are captured by value.
cout << x << " " << y << endl;
}
Дополнительные сведения о generate_n функции, см. generate_n.Дополнительные сведения о for_each функции, см. for_each.
В следующих разделах описаны грамматики лямбда-выражения и как относится каждый элемент в предыдущем примере.
Грамматика выражения лямбда
Следующие формальное определение показывает грамматики в формате БНФ лямбда-выражение:
лямбда-выражения
: Лямбда-параметр introducer лямбда объявленияopt сложных инструкций
лямбда introducer
: [lambda-captureopt]
лямбда захвата
: по умолчанию записи
| список записи
| по умолчанию запись,список записи
по умолчанию записи
: &
| =
список записи
: записи
| записи списка,записи
захват
: идентификатор
| &Идентификатор
| this
Лямбда-параметр объявления
: (Лямбда параметр объявление списокopt) изменяемые спецификацииopt Спецификация исключенийopt лямбда Возврат типа предложениеopt
Лямбда параметр объявление списка
: Лямбда-параметр
| Лямбда-параметр,Лямбда параметр объявление списка
Лямбда-параметр
: декларатор decl спецификатор seq
лямбда Возврат типа предложение
: ->type-id
В следующем разделе описано, как грамматики относится к примеру во введении.
Свойства лямбда-выражения
На приведенном ниже рисунке сопоставляет грамматики в примере.
Выноски в иллюстрации выглядят следующим образом:
лямбда introducer (называется захвата предложение далее в этом разделе)
Лямбда параметр объявление список (называется список параметров далее в этом разделе)
Изменяемые спецификации (называется изменяемые спецификации далее в этом разделе)
спецификация исключений (называется Спецификация исключений далее в этом разделе)
лямбда Возврат типа предложение (называется возвращаемый тип далее в этом разделе)
оператор сложных (называется тела лямбда-выражения далее в этом разделе)
Грамматика более подробно в следующих разделах.
Захват предложение
Лямбда-выражения можно получить доступ к любой переменной, длительностью хранения автоматически и может осуществляться в области видимости.Предложение записи указывает ли тело лямбда-выражение обращается к переменным в области видимости по значению или по ссылке: переменные, имеющие амперсанд (&) префикс осуществляется путем ссылки и переменные, которые не имеют & префикс осуществляется по значению.Предложение пустой записи [], указывает, что тело лямбда-выражение обращается к нет переменных в области видимости.
Режим записи по умолчанию указывает, регистрируются ли записи переменных, которые явно не указано, по значению или по ссылке.Можно задать режим записи по умолчанию (capture-default в синтаксисе), указав & или = как первый элемент предложения захвата.& Элемент указывает, что тело лямбда-выражение обращается все захваченные переменные по ссылке, явно указано иное.= Элемент указывает, что тело лямбда-выражение обращается все захваченные переменные по значению, явно указано иное.Например, если тело лямбда-выражение обращается к внешней переменной total по ссылке и Внешняя переменная factor по значению, затем следующие записи предложения эквивалентны:
[&total, factor]
[&, factor]
[=, &total]
Можно использовать лямбда-выражения в теле метода класса.Передать this указатель записи предложения для обеспечения доступа к членам методы и данные, включающего класса.Пример использования лямбда-выражение с помощью методов класса см. Пример: с помощью лямбда-выражения в метод в разделе Примеры лямбда-выражений.
Список параметров
Список параметров лямбда-выражение напоминает список параметров для функции, за исключением следующих:
Список параметров не может иметь аргументы по умолчанию.
Список параметров не может иметь список аргументов переменной длины.
Список параметров не могут иметь безымянные параметры.
Лямбда-выражение может занять другое лямбда-выражение в качестве аргумента.Дополнительные сведения см в разделе высшего порядка лямбда-выражения Примеры лямбда-выражений.
Список параметров лямбда-выражение не является обязательным.Список параметров можно опустить, если лямбда-выражение не передать аргументы и не предоставляют mutable-specification, exception-specification, и lambda-return-type-clause элементов.Следующий пример показывает опускает в списке параметров лямбда-выражение:
// lambda_parameter_list.cpp
int main()
{
int x = 4;
int y = 5;
int z = [=] { return x + y; }();
}
Изменяемые спецификации
Спецификация изменяемых частей включает тело лямбда-выражения для изменения переменных, которые фиксируются по значению.В предыдущем примере используется mutable ключевое слово, тело лямбда-выражения можно изменить его копии внешних переменных x и y, который захватывает лямбда-выражение, значение.Поскольку лямбда-выражение захватывает переменные x и y по значению, их значения остаются 1 после вызова generate_n.
Спецификация исключений
Можно использовать throw() спецификация исключений, чтобы указать, что лямбда-выражение не выдает никаких исключений.Как с помощью обычных функций компилятор Visual C++ создает предупреждение ошибку C4297 Если лямбда-выражение объявлено throw() спецификация исключений и тела лямбда-выражения создает исключение, как показано в следующем примере:
// throw_lambda_expression.cpp
int main() // C4297 expected
{
[]() throw() { throw 5; }();
}
Дополнительные сведения о спецификации исключений см. Спецификации исключений.
Возвращаемый тип
Возвращаемый тип часть лямбда-выражения похож на тип возвращаемого часть обычного метода или функции.Тем не менее, возвращаемый тип соответствует списку параметров и должны включать -> перед возвращаемым типом.
Возвращаемый тип часть лямбда-выражения можно опустить, если тела лямбда-выражения содержит один оператор return или лямбда-выражение возвращает значение.Если тела лямбда-выражения состоит из одной инструкции return, компилятор deduces возвращаемый тип из типа возвращаемого выражения.В противном случае компилятор deduces возвращаемый тип для void.
Лямбда-выражении может привести к другим лямбда-выражение, как ее возвращаемое значение.Дополнительные сведения см в разделе высшего порядка лямбда-выражения Примеры лямбда-выражений.
Тела лямбда-выражения
Части тела лямбда лямбда-выражения могут содержать все, что может содержать тело обычного метода или функции.Тело обычного функции и лямбда-выражения можно получить доступ к следующие типы переменных:
Параметры
Локально объявленных переменных
Члены данных класса (когда объявлен внутри класса)
Любой переменной, которая имеет длительность хранения статические (глобальные переменные)
Кроме того лямбда-выражения можно получить доступ к переменные, которые собирает из области видимости.Переменная является явно записанные Если в предложении захвата лямбда-выражение.В противном случае переменная является неявно захваченного.Тело лямбда-выражение использует режим записи по умолчанию доступ к переменным, неявно захвата.
lambda_parameter_list.cpp Пример неявно захватывает локальные переменные x и y по значению.В следующем примере содержится лямбда-выражение, явно захватывает переменную n по значению и неявно захватывает переменную m по ссылке:
// captures_lambda_expression.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main()
{
int m = 0, n = 0;
[&, n] (int a) mutable { m = ++n + a; }(4);
cout << m << endl << n << endl;
}
Этот пример выводит на консоль следующее:
5
0
Поскольку переменная n записи по значению, остается его значение 0 после вызова лямбда-выражение.
Несмотря на то, что лямбда-выражения можно записывать только переменные, имеющие длительность хранения автоматически, можно использовать переменные, имеющие длительность хранения статических данных в теле лямбда-выражения.В следующем примере используется generate функции и лямбда-выражение для присваивания значения для каждого элемента в vector объект.Лямбда-выражения изменяет статическую переменную для создания значения следующего элемента.
// lambda_static_variable.cpp
// compile with: /c /EHsc
#include <vector>
#include <algorithm>
using namespace std;
void fillVector(vector<int>& v)
{
// A local static variable.
static int nextValue = 1;
// The lambda expression that appears in the following call to
// the generate function modifies and uses the local static
// variable nextValue.
generate(v.begin(), v.end(), [] { return nextValue++; });
}
Дополнительные сведения о generate функции, см. generate.