Поделиться через


Синтаксис лямбда-выражения

В этом разделе описывается синтаксис лямбда-выражения.Он предоставляет пример, демонстрирующий структурных элементов лямбда-выражения и как эти элементы относятся к примеру.

Следующая программа использует лямбда-выражения с двумя алгоритмы библиотеки 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

В следующем разделе описано, как грамматики относится к примеру во введении.

Свойства лямбда-выражения

На приведенном ниже рисунке сопоставляет грамматики в примере.

Структурные элементы лямбда-выражения

Выноски в иллюстрации выглядят следующим образом:

  1. лямбда introducer (называется захвата предложение далее в этом разделе)

  2. Лямбда параметр объявление список (называется список параметров далее в этом разделе)

  3. Изменяемые спецификации (называется изменяемые спецификации далее в этом разделе)

  4. спецификация исключений (называется Спецификация исключений далее в этом разделе)

  5. лямбда Возврат типа предложение (называется возвращаемый тип далее в этом разделе)

  6. оператор сложных (называется тела лямбда-выражения далее в этом разделе)

Грамматика более подробно в следующих разделах.

Dd293603.collapse_all(ru-ru,VS.110).gifЗахват предложение

Лямбда-выражения можно получить доступ к любой переменной, длительностью хранения автоматически и может осуществляться в области видимости.Предложение записи указывает ли тело лямбда-выражение обращается к переменным в области видимости по значению или по ссылке: переменные, имеющие амперсанд (&) префикс осуществляется путем ссылки и переменные, которые не имеют & префикс осуществляется по значению.Предложение пустой записи [], указывает, что тело лямбда-выражение обращается к нет переменных в области видимости.

Режим записи по умолчанию указывает, регистрируются ли записи переменных, которые явно не указано, по значению или по ссылке.Можно задать режим записи по умолчанию (capture-default в синтаксисе), указав & или = как первый элемент предложения захвата.& Элемент указывает, что тело лямбда-выражение обращается все захваченные переменные по ссылке, явно указано иное.= Элемент указывает, что тело лямбда-выражение обращается все захваченные переменные по значению, явно указано иное.Например, если тело лямбда-выражение обращается к внешней переменной total по ссылке и Внешняя переменная factor по значению, затем следующие записи предложения эквивалентны:

[&total, factor]
[&, factor]
[=, &total]

Можно использовать лямбда-выражения в теле метода класса.Передать this указатель записи предложения для обеспечения доступа к членам методы и данные, включающего класса.Пример использования лямбда-выражение с помощью методов класса см. Пример: с помощью лямбда-выражения в метод в разделе Примеры лямбда-выражений.

Dd293603.collapse_all(ru-ru,VS.110).gifСписок параметров

Список параметров лямбда-выражение напоминает список параметров для функции, за исключением следующих:

  • Список параметров не может иметь аргументы по умолчанию.

  • Список параметров не может иметь список аргументов переменной длины.

  • Список параметров не могут иметь безымянные параметры.

Лямбда-выражение может занять другое лямбда-выражение в качестве аргумента.Дополнительные сведения см в разделе высшего порядка лямбда-выражения Примеры лямбда-выражений.

Список параметров лямбда-выражение не является обязательным.Список параметров можно опустить, если лямбда-выражение не передать аргументы и не предоставляют 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; }();
}

Dd293603.collapse_all(ru-ru,VS.110).gifИзменяемые спецификации

Спецификация изменяемых частей включает тело лямбда-выражения для изменения переменных, которые фиксируются по значению.В предыдущем примере используется mutable ключевое слово, тело лямбда-выражения можно изменить его копии внешних переменных x и y, который захватывает лямбда-выражение, значение.Поскольку лямбда-выражение захватывает переменные x и y по значению, их значения остаются 1 после вызова generate_n.

Dd293603.collapse_all(ru-ru,VS.110).gifСпецификация исключений

Можно использовать throw() спецификация исключений, чтобы указать, что лямбда-выражение не выдает никаких исключений.Как с помощью обычных функций компилятор Visual C++ создает предупреждение ошибку C4297 Если лямбда-выражение объявлено throw() спецификация исключений и тела лямбда-выражения создает исключение, как показано в следующем примере:

// throw_lambda_expression.cpp
int main() // C4297 expected
{
   []() throw() { throw 5; }();
}

Дополнительные сведения о спецификации исключений см. Спецификации исключений.

Dd293603.collapse_all(ru-ru,VS.110).gifВозвращаемый тип

Возвращаемый тип часть лямбда-выражения похож на тип возвращаемого часть обычного метода или функции.Тем не менее, возвращаемый тип соответствует списку параметров и должны включать -> перед возвращаемым типом.

Возвращаемый тип часть лямбда-выражения можно опустить, если тела лямбда-выражения содержит один оператор return или лямбда-выражение возвращает значение.Если тела лямбда-выражения состоит из одной инструкции return, компилятор deduces возвращаемый тип из типа возвращаемого выражения.В противном случае компилятор deduces возвращаемый тип для void.

Лямбда-выражении может привести к другим лямбда-выражение, как ее возвращаемое значение.Дополнительные сведения см в разделе высшего порядка лямбда-выражения Примеры лямбда-выражений.

Dd293603.collapse_all(ru-ru,VS.110).gifТела лямбда-выражения

Части тела лямбда лямбда-выражения могут содержать все, что может содержать тело обычного метода или функции.Тело обычного функции и лямбда-выражения можно получить доступ к следующие типы переменных:

  • Параметры

  • Локально объявленных переменных

  • Члены данных класса (когда объявлен внутри класса)

  • Любой переменной, которая имеет длительность хранения статические (глобальные переменные)

Кроме того лямбда-выражения можно получить доступ к переменные, которые собирает из области видимости.Переменная является явно записанные Если в предложении захвата лямбда-выражение.В противном случае переменная является неявно захваченного.Тело лямбда-выражение использует режим записи по умолчанию доступ к переменным, неявно захвата.

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.

См. также

Ссылки

Lambda expressions in C++

Примеры лямбда-выражений

generate

generate_n

for_each

Спецификации исключений

Предупреждение компилятора (уровень 1) C4297