Składni wyrażenia lambda
W tym temacie opisano składnię wyrażenia lambda.Stanowi przykład demonstrujący elementy strukturalne wyrażenie lambda i w jaki sposób elementy te odnoszą się do przykładu.
Następujący program używa wyrażenia lambda dwóch algorytmów STL: generate_n i for_each.Wyrażenia lambda, która pojawia się w wywołaniu generate_n funkcja przypisuje element vector obiektu do sumy dwóch poprzednich elementów.Wyrażenia lambda, która pojawia się w wywołaniu for_each funkcji drukuje elementu tego samego vector obiektu do konsoli.
// 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;
}
Aby uzyskać więcej informacji o generate_n działać, zobacz generate_n.Aby uzyskać więcej informacji o for_each działać, zobacz for_each.
W poniższych sekcjach opisano gramatyki wyrażenie lambda i jak każdy element odnosi się do poprzedniego przykładu.
Gramatyka wyrażenia lambda
Następujące definicje formalne pokazuje gramatyki, w formacie BNF wyrażenie lambda:
wyrażenie lambda
: lambda wprowadzający w lambda deklaracji parametruopt związek oświadczenie
lambda wprowadzający
: [lambda-captureopt]
lambda przechwytywania
: domyślne przechwytywania
| Lista przechwytywania
| domyślne przechwytywania,listy przechwytywania
domyślne przechwytywania
: &
| =
Lista przechwytywania
: Przechwytywanie
| Lista przechwytywania,Przechwytywanie
Przechwytywanie
: identyfikator
| &Identyfikator
| this
Deklaracja parametru lambda
: (lambda parametr deklaracja listaopt) tych specyfikacjiopt specyfikacji wyjątekopt lambda-return typ klauzuliopt
lambda parametr deklaracja lista
: parametr lambda
| Parametr lambda,lambda parametr deklaracja lista
Parametr lambda
: decl specyfikatora seq; niewłaściwy deklarator
lambda-return typ klauzula
: ->type-id
W poniższej sekcji opisano, jak na przykład wprowadzenie odnosi się gramatyki.
Właściwości wyrażenia Lambda
Następująca ilustracja mapuje gramatyki przykładu.
Objaśnienia na ilustracji, są następujące:
lambda wprowadzający (zwane Przechwytywanie klauzuli dalej w tym temacie)
lambda parametr deklaracja lista (zwane listy parametrów dalej w tym temacie)
Specyfikacja tych (zwane tych specyfikacji dalej w tym temacie)
Specyfikacja wyjątek (zwane specyfikacji wyjątek dalej w tym temacie)
lambda-return typ klauzuli (zwane zwraca typ dalej w tym temacie)
Instrukcja związek (zwane organ lambda dalej w tym temacie)
W poniższych sekcjach opisano gramatyki bardziej szczegółowo.
Przechwytywanie klauzuli
Wyrażenie lambda można uzyskać dostęp do dowolnej zmiennej, których czas trwania automatycznego przechowywania i który może być dostępny w zakresie okalającego.Klauzula przechwytywania określa, czy jednostka wyrażenie lambda uzyskuje dostęp do zmiennych w zakresie otaczający, przez wartość lub przez odwołanie: zmienne, które mają znak ampersand (&) prefiks są dostępne dla odwołania i zmiennych, które nie mają & wartości są dostępne dla prefiksu.Klauzula pusty przechwytywania [], wskazuje organ wyrażenie lambda uzyskuje dostęp do zmiennych otaczający zakres.
Domyślny tryb przechwytywania Określa, czy zmienne przechwytywania, które jawnie nie określisz są przechwytywane przez wartość lub przez odwołanie.Można określić domyślny tryb przechwytywania (capture-default w składni) określając & lub = jako pierwszy element klauzuli przechwytywania.& Element określa, że jednostka wyrażenie lambda dostęp do wszystkich przechwyconych zmiennych poprzez odniesienie, chyba że wyraźnie określono inaczej.= Element określa, że jednostka wyrażenie lambda dostęp do zmiennych wszystkich przechwyconych przez wartość, chyba że wyraźnie określono inaczej.Na przykład, jeśli jednostka wyrażenie lambda uzyskuje dostęp do zewnętrznych zmiennej total o zmiennej zewnętrznych i factor przez wartość, następnie następujące klauzule przechwytywania są równoważne:
[&total, factor]
[&, factor]
[=, &total]
Można użyć wyrażenia lambda w treści metody klasy.Przekazać this wskaźnik klauzuli przechwytywania, aby zapewnić dostęp do metod i danych członków otaczający klasy.Na przykład jak używać wyrażenia lambda z metod klasy, zobacz przykład: w metodzie w temacie za pomocą wyrażenia Lambda Przykłady wyrażeń Lambda.
Lista parametrów
Lista parametrów dla wyrażenia lambda jest podobna do listy parametrów dla funkcji, z następującymi wyjątkami:
Lista parametrów nie może mieć argumentów domyślne.
Lista parametrów nie może mieć listy argumentów o zmiennej długości.
Lista parametrów nie nienazwanych parametrów.
Wyrażenie lambda można podjąć innego wyrażenia lambda jako argumentu.Aby uzyskać więcej informacji, zobacz wyższego rzędu Lambda wyrażeń w temacie Przykłady wyrażeń Lambda.
Lista parametrów dla wyrażenia lambda jest opcjonalne.Lista parametrów można pominąć, jeśli nie przekazywać argumenty do wyrażenia lambda i nie mutable-specification, exception-specification, i lambda-return-type-clause elementy.Wyrażenie lambda, pomijające listy parametrów można znaleźć w poniższym przykładzie:
// lambda_parameter_list.cpp
int main()
{
int x = 4;
int y = 5;
int z = [=] { return x + y; }();
}
Tych specyfikacji.
Część tych specyfikacji umożliwia organ wyrażenie lambda do modyfikacji zmiennych, które są przechwytywane przez wartość.W poprzednim przykładzie użyto mutable słowa kluczowego tak, aby organ wyrażenie lambda można modyfikować jego kopie zmiennych zewnętrznych x i y, który przechwytuje wyrażenie lambda przez wartość.Ponieważ wyrażenie lambda przechwytuje zmiennych x i y przez wartość, ich wartości są nadal 1 po wywołaniu generate_n.
Specyfikacja wyjątek
Można użyć throw() specyfikacji wyjątek, aby wskazać, że wyrażenie lambda generują wyjątki.Jak regularne funkcje kompilatora Visual C++ generuje ostrzeżenie C4297 , jeśli wyrażenie lambda deklaruje throw() wyjątek specyfikacji i organ lambda generuje wyjątek, jak pokazano w następującym przykładzie:
// throw_lambda_expression.cpp
int main() // C4297 expected
{
[]() throw() { throw 5; }();
}
Aby uzyskać więcej informacji o wyjątku specyfikacji, zobacz Specyfikacje wyjątek.
Zwracany typ
Zwracany typ części wyrażenia lambda jest podobna do części zwracany typ metody zwykłe lub funkcji.Jednakże typ zwracany następuje lista parametrów i musi zawierać -> przed typ zwracany.
Zwracany typ części wyrażenia lambda można pominąć, jeśli treść lambda zawiera pojedynczej instrukcji return lub wyrażenie lambda nie zwraca wartości.Jeżeli organ lambda składa się z pojedynczej instrukcji return, kompilator deduces zwracany typ od typu return wyrażenie.W przeciwnym razie kompilator deduces typ zwracany za void.
Wyrażenie lambda może prowadzić do innego wyrażenia lambda jako swojej zwracanej wartości.Aby uzyskać więcej informacji, zobacz wyższego rzędu Lambda wyrażeń w temacie Przykłady wyrażeń Lambda.
Organ lambda
Części ciała lambda wyrażenia lambda może zawierać wszystko, co może zawierać treści metody zwykłe lub funkcji.Treść zwykłej funkcji i wyrażenie lambda może uzyskać dostęp do następujących typów zmiennych:
Parametry
Zmienne zadeklarowane lokalnie
Elementy danych klas (gdy zadeklarowana wewnątrz klasy)
Wszystkie zmienne statyczne przechowywanie w czasie trwania (na przykład, zmienne globalne)
Wyrażenie lambda można uzyskać dostęp zmiennych, które przechwytuje go z zakresu okalającego.Zmienna jest jawnie przechwycone występuje w klauzuli przechwytywania wyrażenia lambda.W przeciwnym razie jest zmienna niejawnie przechwycone.Jednostka wyrażenie lambda wykorzystuje domyślny tryb przechwytywania do zmiennych dostępu, które są niejawnie przechwytywane.
lambda_parameter_list.cpp Przykład niejawnie przechwytuje zmiennych lokalnych x i y przez wartość.Poniższy przykład zawiera wyrażenie lambda, który przechwytuje jawnie zmiennej n przez wartość i niejawnie przechwytuje zmiennej m przez odniesienie:
// 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;
}
W tym przykładzie drukuje następujące do konsoli:
5
0
Ponieważ zmienna n przez wartość, jego wartość pozostaje 0 po wywołaniu wyrażenie lambda.
Chociaż przechwycić wyrażenie lambda zmiennych do automatycznego przechowywania czas trwania, można używać zmiennych czas trwania składowania statycznych w treści wyrażenie lambda.W poniższym przykładzie użyto generate funkcji i wyrażenie lambda do przypisania wartości do każdego elementu w vector obiektu.Wyrażenie lambda modyfikuje zmienna statyczna, aby wygenerować wartość następnego elementu.
// 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++; });
}
Aby uzyskać więcej informacji o generate działać, zobacz generate.