Sintaxe de expressões lambda
Este tópico descreve a sintaxe de expressões lambda.Ele fornece um exemplo que demonstra os elementos estruturais de uma expressão lambda e como esses elementos se relacionam com o exemplo.
O programa a seguir usa expressões lambda com dois algoritmos da STL: generate_n e for_each.A expressão lambda que aparece na chamada para o generate_n função atribui um elemento de uma vector o objeto para a soma dos dois elementos anteriores.A expressão lambda que aparece na chamada para o for_each função imprime um elemento do mesmo vector o objeto para o console.
// 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 obter mais informações sobre o generate_n função, consulte generate_n.Para obter mais informações sobre o for_each função, consulte for_each.
As seções a seguir descrevem a gramática de uma expressão lambda e como cada elemento se relaciona ao exemplo anterior.
Gramática de expressão lambda
A seguinte definição formal mostra a gramática no formato BNF, de uma expressão lambda:
expressão lambda
: Introdutor de lambda lambda parâmetro declaraçãoopt declaração composto
Introdutor de lambda
: [lambda-captureopt]
captura de lambda
: padrão de captura
| lista de captura
| padrão de captura,lista de captura
padrão de captura
: &
| =
lista de captura
: de captura
| lista de captura,de captura
captura
: identificador
| &identificador
| this
declaração de parâmetro lambda
: (lambda declaração-lista de parâmetros deopt) mutável especificaçãoopt especificação de exceçãoopt lambda retorno-tipo de cláusulaopt
lambda declaração-lista de parâmetros
: parâmetro lambda
| o parâmetro lambda,lambda declaração-lista de parâmetros
parâmetro lambda
: Declarador seq de especificador de decl
cláusula lambda-retorno-tipo
: ->type-id
A seção a seguir descreve como a gramática se relaciona com o exemplo na introdução.
Propriedades de expressões Lambda
A ilustração a seguir mapeia a gramática para o exemplo.
Textos explicativos na ilustração são:
Introdutor de lambda (conhecido como capturar cláusula posteriormente neste tópico)
lambda declaração-lista de parâmetros de (conhecido como lista de parâmetros posteriormente neste tópico)
especificação mutável (conhecido como especificação mutável posteriormente neste tópico)
especificação de exceção (conhecido como especificação de exceção posteriormente neste tópico)
lambda-retorno tipo cláusula (conhecido como o tipo de retorno posteriormente neste tópico)
declaração de compostos (conhecido como corpo do lambda posteriormente neste tópico)
As seções a seguir descrevem a gramática em mais detalhes.
Cláusula de captura
Uma expressão lambda pode acessar qualquer variável que tem duração de armazenamento automático e que pode ser acessado no escopo delimitador.A cláusula de captura Especifica se o corpo da expressão lambda acessa variáveis no escopo delimitador por valor ou por referência: variáveis que têm o e comercial (&) prefixo são acessados por referência e variáveis que não têm o & prefixo são acessados por valor.A cláusula de captura vazia, [], indica que o corpo da expressão lambda acessa sem variáveis no escopo delimitador.
O modo de captura padrão Especifica se as variáveis de captura que você não especificar explicitamente são capturadas por valor ou por referência.Você pode especificar o modo de captura padrão (capture-default na sintaxe), especificando & ou = como o primeiro elemento da cláusula de captura.O & elemento Especifica que o corpo da expressão lambda acessa variáveis todas capturadas por referência, a menos que você explicitamente especifique o contrário.O = elemento Especifica que o corpo da expressão lambda acessa variáveis todas capturadas por valor, a menos que você explicitamente especifique o contrário.Por exemplo, se o corpo de uma expressão lambda acessa a variável externa total por referência e variável externa factor por valor, em seguida, as cláusulas de captura a seguir são equivalentes:
[&total, factor]
[&, factor]
[=, &total]
Você pode usar expressões lambda no corpo de um método de classe.Passar o this ponteiro para a cláusula de captura para fornecer acesso para os membros de dados e métodos da classe delimitador.Para obter um exemplo de como usar a expressão lambda com métodos de classe, consulte exemplo: usando uma expressão Lambda em um método no tópico Exemplos de expressões Lambda.
Lista de parâmetros
Lista de parâmetros para uma expressão lambda é semelhante a lista de parâmetros para uma função com as seguintes exceções:
Lista de parâmetros não pode ter argumentos padrão.
Lista de parâmetros não pode ter uma lista de argumentos de comprimento variável.
Lista de parâmetros não pode ter parâmetros sem nome.
Uma expressão lambda pode levar a outra expressão lambda como seu argumento.Para obter mais informações, consulte expressões Lambda de ordem superior no tópico Exemplos de expressões Lambda.
Lista de parâmetros para uma expressão lambda é opcional.Você pode omitir a lista de parâmetro se você não passar argumentos para a expressão lambda e você não fornecer o mutable-specification, exception-specification, e lambda-return-type-clause elementos.O exemplo a seguir mostra uma expressão lambda que omite a lista de parâmetros:
// lambda_parameter_list.cpp
int main()
{
int x = 4;
int y = 5;
int z = [=] { return x + y; }();
}
Especificação mutável
A parte mutável especificação permite que o corpo de uma expressão lambda para modificar as variáveis que são capturadas pelo valor.O exemplo anterior usa o mutable palavra-chave para que o corpo da expressão lambda pode modificar suas cópias das variáveis externas x e y, que a expressão lambda captura por valor.Porque a expressão lambda captura as variáveis x e y por valor, seus valores permanecem 1 após a chamada para generate_n.
Especificação de exceção
Você pode usar o throw() especificação de exceção para indicar que a expressão lambda não lançar exceções.Como com funções regulares, o compilador Visual C++ gera aviso C4297 se uma expressão lambda declara o throw() especificação de exceção e o corpo do lambda lança uma exceção, conforme mostrado no exemplo a seguir:
// throw_lambda_expression.cpp
int main() // C4297 expected
{
[]() throw() { throw 5; }();
}
Para obter mais informações sobre especificações de exceção, consulte Especificações de exceção.
Tipo de retorno
A parte do tipo de retorno de uma expressão lambda é semelhante a parte do tipo de retorno de uma função ou um método comum.No entanto, o tipo de retorno segue a lista de parâmetros e deve incluir -> antes do tipo de retorno.
Se o corpo do lambda contém uma única instrução de retorno ou a expressão lambda não retorna um valor, você pode omitir a parte do tipo de retorno de uma expressão lambda.Se o corpo do lambda consiste em uma única instrução de retorno, o compilador deduz o tipo de retorno do tipo da expressão de retorno.Caso contrário, o compilador deduz o tipo de retorno para ser void.
Uma expressão lambda pode produzir outra expressão lambda como valor de retorno.Para obter mais informações, consulte expressões Lambda de ordem superior no tópico Exemplos de expressões Lambda.
Corpo do lambda
A parte do corpo de uma expressão lambda lambda pode conter tudo o que o corpo de uma função ou um método comum pode conter.O corpo de uma função comum e uma expressão lambda pode acessar os seguintes tipos de variáveis:
Parâmetros
Variáveis declaradas localmente
Membros de dados de classe (quando declaradas dentro de uma classe)
Qualquer variável de duração de armazenamento estático (por exemplo, variáveis globais)
Além disso, uma expressão lambda pode acessar variáveis captura do escopo delimitador.Uma variável é explicitamente capturadas se ele aparecer na cláusula de captura da expressão lambda.Caso contrário, a variável é implicitamente capturados.O corpo da expressão lambda usa o modo de captura padrão para variáveis de acesso implicitamente são capturados.
O lambda_parameter_list.cpp exemplo captura implicitamente variáveis locais x e y por valor.O exemplo a seguir contém uma expressão lambda que captura explicitamente a variável n pelo valor e implicitamente captura a variável m por referência:
// 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 exemplo imprime o seguinte ao console:
5
0
Porque a variável n é capturado pelo valor, seu valor permanece 0 após a chamada para a expressão lambda.
Embora uma expressão lambda pode capturar apenas variáveis que tenham duração armazenamento automático, você pode usar variáveis têm duração de armazenamento estático no corpo de uma expressão lambda.O exemplo a seguir usa o generate função e uma expressão lambda para atribuir um valor para cada elemento de uma vector objeto.A expressão lambda modifica a variável estática para gerar o valor do próximo elemento.
// 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 obter mais informações sobre o generate função, consulte generate.