Compartir a través de


Sintaxis de la expresión lambda

Este tema describe la sintaxis de las expresiones lambda.Proporciona un ejemplo que muestra los elementos estructurales de una expresión lambda y cómo se relacionan estos elementos en el ejemplo.

El siguiente programa utiliza las expresiones lambda con los dos algoritmos STL: generate_n y for_each.La expresión lambda que aparece en la llamada a la generate_n función asigna un elemento de un vector objeto a la suma de los dos elementos anteriores.La expresión lambda que aparece en la llamada a la for_each función imprime un elemento de la misma vector objeto a la consola.

// 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;
}

Para obtener más información acerca de la generate_n de función, consulte generate_n.Para obtener más información acerca de la for_each de función, consulte for_each.

Las secciones siguientes describen la gramática de una expresión lambda y cómo se relaciona cada elemento con el ejemplo anterior.

Gramática de expresión lambda

La siguiente definición formal, muestra la gramática, en formato BNF, de una expresión lambda:

expresión lambda

   : iniciador de lambda lambda parámetro declaración-de-opt instrucción-compuesto

iniciador de lambda

   : [lambda-captureopt]

captura de lambda

   : captura predeterminada

   | lista de captura

   | captura predeterminada,lista de captura

captura predeterminada

   : &

   | =

lista de captura

   : de captura

   | lista de captura de,de captura

captura

   : identificador

   | &identificador

   | this

declaración de parámetro lambda

   : (lambda-declaración de lista de parámetrosopt) mutable especificaciónoptar por especificación de excepcionesopt lambda-devolución-tipo-clauseopt

lambda-declaración de lista de parámetros

   : el parámetro lambda

   | el parámetro lambda,lambda-declaración de lista de parámetros

parámetro lambda

   : declarador decl-especificador-seq.

lambda-devolución-tipo-clause

   : ->type-id

En la siguiente sección se describe cómo se relaciona con la gramática en el ejemplo de la introducción.

Propiedades de las expresiones Lambda

En la ilustración siguiente se asigna la gramática a del ejemplo.

Los elementos estructurales de una expresión lambda

Los rótulos en la ilustración son los siguientes:

  1. iniciador de lambda (denominados captura cláusula más adelante en este tema)

  2. lambda-declaración de lista de parámetros (denominados lista de parámetros de más adelante en este tema)

  3. mutable especificación (denominados especificación mutable más adelante en este tema)

  4. especificación de excepción (denominados una especificación de excepción más adelante en este tema)

  5. lambda-devolución-tipo-clause (denominados tipo de valor devuelto más adelante en este tema)

  6. instrucción compuesto (denominados cuerpo lambda más adelante en este tema)

Las secciones siguientes describen la gramática con más detalle.

Dd293603.collapse_all(es-es,VS.110).gifCláusula de captura

Una expresión lambda puede tener acceso a cualquier variable que tiene duración de almacenamiento automático y que se puede tener acceso en el ámbito envolvente.La cláusula de captura especifica si el cuerpo de la expresión lambda tiene acceso a las variables del ámbito envolvente por valor o por referencia: variables que tienen el signo de y comercial (&) prefijo se tiene acceso por referencia y las variables que no tienen la & prefijo se accede a ellos por valor.La cláusula captura vacía, [], indica que el cuerpo de la expresión lambda tiene acceso a ninguna variable en el ámbito envolvente.

El modo de captura predeterminada especifica si se capturan las variables de captura que no se especifica explícitamente por valor o por referencia.Puede especificar el modo de captura predeterminada (capture-default en la sintaxis) mediante la especificación de & o = como el primer elemento de la cláusula de captura.El & elemento especifica el cuerpo de la expresión lambda que tiene acceso a las variables capturadas todo por referencia a menos que se especifique explícitamente lo contrario.El = elemento especifica el cuerpo de la expresión lambda que tiene acceso a las variables capturadas todo por valor a menos que se especifique explícitamente lo contrario.Por ejemplo, si el cuerpo de una expresión lambda tiene acceso a la variable externa total por referencia y la variable externa factor por valor, a continuación, las cláusulas de captura siguientes son equivalentes:

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

Puede utilizar las expresiones lambda en el cuerpo de un método de clase.Pasar la this puntero a la cláusula de captura para proporcionar acceso a los miembros de datos y los métodos de la clase envolvente.Para obtener un ejemplo de cómo utilizar la expresión lambda con los métodos de clase, vea ejemplo: el uso de una expresión Lambda en un método en el tema Ejemplos de expresiones lambda.

Dd293603.collapse_all(es-es,VS.110).gifLista de parámetros

La lista de parámetros para una expresión lambda es similar a la lista de parámetros para una función, con las siguientes excepciones:

  • La lista de parámetros no tiene argumentos predeterminados.

  • La lista de parámetros no puede tener una lista de argumentos de longitud variable.

  • La lista de parámetros no puede tener parámetros sin nombre.

Una expresión lambda puede tomar otra expresión lambda como su argumento.Para obtener más información, vea expresiones Lambda de orden superior en el tema Ejemplos de expresiones lambda.

La lista de parámetros para una expresión lambda es opcional.Puede omitir la lista de parámetros si no se pasan argumentos a la expresión lambda y no proporcionan la mutable-specification, exception-specification, y lambda-return-type-clause elementos.En el ejemplo siguiente se muestra una expresión lambda que omite la lista de parámetros:

// lambda_parameter_list.cpp
int main()
{
   int x = 4;
   int y = 5;
   int z = [=] { return x + y; }();
}

Dd293603.collapse_all(es-es,VS.110).gifEspecificación mutable

La parte de la especificación mutable permite que el cuerpo de una expresión lambda para modificar las variables que se capturan por valor.En el ejemplo anterior se utiliza el mutable palabra clave para que el cuerpo de la expresión lambda puede modificar sus copias de las variables externas x y y, que captura de la expresión lambda por valor.Debido a que la expresión lambda captura las variables de x y y por valor, siendo sus valores 1 después de llamar a generate_n.

Dd293603.collapse_all(es-es,VS.110).gifEspecificación de excepciones

Puede utilizar el throw() una especificación de excepción para indicar que la expresión lambda no produce ninguna excepción.Como con las funciones normales, el compilador de Visual C++ genera la advertencia la advertencia C4297 si una expresión lambda se declara el throw() una especificación de excepción y el cuerpo de lambda produce una excepción, tal como se muestra en el ejemplo siguiente:

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

Para obtener más información acerca de las especificaciones de excepción, consulte Especificaciones de excepciones.

Dd293603.collapse_all(es-es,VS.110).gifReturn Type

La parte de tipo de valor devuelto de una expresión lambda es similar a la parte de tipo de valor devuelto de una función o método ordinario.Sin embargo, el tipo de valor devuelto sigue a la lista de parámetros y debe incluir -> delante del tipo de valor devuelto.

Puede omitir la parte de tipo de valor devuelto de una expresión lambda si el cuerpo de lambda contiene una única instrucción de devolución o la expresión lambda no devuelve un valor.Si el cuerpo de lambda consta de una única instrucción de retorno, el compilador deduce el tipo de valor devuelto desde el tipo de la expresión de valor devuelto.De lo contrario el compilador deduce el tipo de valor devuelto para ser void.

Una expresión lambda puede producir otra expresión lambda como su valor devuelto.Para obtener más información, vea expresiones Lambda de orden superior en el tema Ejemplos de expresiones lambda.

Dd293603.collapse_all(es-es,VS.110).gifCuerpo de lambda

La parte del cuerpo de una expresión lambda lambda puede contener todo lo que puede contener el cuerpo de un método normal o una función.El cuerpo de una función normal y una expresión lambda puede tener acceso a los siguientes tipos de variables:

  • Parámetros

  • Variables declaradas localmente

  • Miembros de datos de clase (cuando se declara dentro de una clase)

  • Cualquier variable cuya duración sea de almacenamiento de información estática (por ejemplo, las variables globales)

Además, una expresión lambda puede tener acceso a las variables que captura del ámbito envolvente.Una variable es capturado explícitamente si aparece en la cláusula de captura de la expresión lambda.De lo contrario, la variable es implícitamente capturado.El cuerpo de la expresión lambda utiliza el modo de captura predeterminada para las variables de acceso que se capturan de forma implícita.

El lambda_parameter_list.cpp ejemplo captura implícitamente las variables locales x y y por valor.El ejemplo siguiente contiene una expresión lambda que captura explícitamente la variable n por valor y implícitamente captura la variable m por referencia:

// 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;
}

Este ejemplo imprime en la consola la siguiente:

5
0

Debido a que la variable n es capturado por valor, su valor permanece 0 después de la llamada a la expresión lambda.

Aunque una expresión lambda sólo puede capturar las variables que tienen una duración de almacenamiento automático, puede utilizar las variables que tienen una duración de almacenamiento de información estática en el cuerpo de una expresión lambda.En el ejemplo siguiente se utiliza el generate función y una expresión lambda para asignar un valor a cada elemento en un vector objeto.La expresión lambda modifica la variable estática para generar el valor del elemento siguiente.

// 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++; });
}

Para obtener más información acerca de la generate de función, consulte generate.

Vea también

Referencia

Expresiones lambda en C++

Ejemplos de expresiones lambda

generate

generate_n

for_each

Especificaciones de excepciones

Advertencia del compilador (nivel 1) C4297