Lambda-Ausdruckssyntax
Dieses Thema beschreibt die Syntax für Lambda-Ausdrücke.Es enthält ein Beispiel, das die strukturellen Elemente eines Lambda-Ausdruck und wie diese Elemente auf das Beispiel veranschaulicht.
Das folgende Programm verwendet Lambda-Ausdrücke mit zwei STL-Algorithmen: generate_n und for_each.Der Lambda-Ausdruck, der im Aufruf der generate_n Funktion weist ein Element der ein vector Objekt, das die Summe aus den vorherigen beiden Elementen.Der Lambda-Ausdruck, der im Aufruf der for_each Funktion druckt ein Element des gleichen vector Objekt in der Konsole.
// 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;
}
Weitere Informationen zu den generate_n funktionieren, finden Sie unter generate_n.Weitere Informationen zu den for_each funktionieren, finden Sie unter for_each.
In den folgenden Abschnitten beschreiben die Grammatik eines Lambda-Ausdruck und wie jedes Element auf das vorherige Beispiel bezieht.
Lambda-Ausdruck-Grammatik
Die folgende formale Definition zeigt die Grammatik in BNF-Format, der einen Lambda-Ausdruck:
Lambda-Ausdruck
: Lambda-Introducer Lambda-Parameterdeklarationopt - Anweisung
Lambda-introducer
: [lambda-captureopt]
Lambda-capture
: Capture-Standard
| Capture-Liste
| Capture-Standard-,Capture-Liste
Capture-Standard
: &
| =
Capture-Liste
: erfassen
| Capture-Liste,erfassen
Erfassen
: Bezeichner
| &Bezeichner
| this
Lambda-Parameters-Deklaration
: (Lambda-Deklaration Parameterlisteopt) änderbaren Spezifikationopt Ausnahmespezifikationopt Lambda-Rückgabe Typ-Klauselopt
Lambda-Deklaration Parameterliste
: Lambda-Parameter
| Lambda-Parameter,Lambda-Deklaration Parameterliste
Lambda-parameter
: Decl-Spezifizierer-Seq-Declarator
Lambda-Rückgabe Typ-Klausel
: ->type-id
Der folgende Abschnitt beschreibt, wie die Grammatik auf das Beispiel in der Einführung bezieht.
Eigenschaften von Lambda-Ausdrücken
In der folgenden Abbildung wird die Grammatik im Beispiel.
Die Positionsnummern in der Abbildung sind wie folgt:
Lambda-Introducer (genannt capture-Klausel weiter unten in diesem Thema)
Lambda-Deklaration Parameterliste (genannt Parameterliste weiter unten in diesem Thema)
änderbare Spezifikation (genannt änderbaren Spezifikation weiter unten in diesem Thema)
Ausnahmespezifikation (genannt Ausnahmespezifikation weiter unten in diesem Thema)
Lambda-Rückgabe Typ-Klausel (genannt Rückgabetyp weiter unten in diesem Thema)
zusammengesetzte Anweisung (genannt Lambda-Text weiter unten in diesem Thema)
In den folgenden Abschnitten beschreiben die Grammatik im Detail.
Klausel erfassen
Ein Lambda-Ausdruck kann eine beliebige Variable zugreifen, die automatische Speicherung Dauer hat und im umschließenden Gültigkeitsbereich zugegriffen werden kann.Die Capture-Klausel gibt an, ob der Hauptteil der Lambda-Ausdruck Variablen im umschließenden Gültigkeitsbereich durch Wert oder Verweis zugreift: Variablen, die das kaufmännische und-Zeichen (&) Präfix erfolgt durch einen Verweis und Variablen, die nicht die & Präfix Wert abgerufen werden.Der leere Capture-Klausel, [], gibt an, dass der Hauptteil der Lambda-Ausdruck keine Variablen im umschließenden Gültigkeitsbereich zugreift.
Die Standard Capture-Modus gibt an, ob Capture Variablen, die Sie nicht explizit angeben durch Wert oder Verweis erfasst werden.Sie können angeben, dass den Standard-Capture-Modus (capture-default in der Syntax) durch die Angabe & oder = als das erste Element der Capture-Klausel.Die & Element angibt, ob der Hauptteil der Lambda-Ausdruck alle erfasste Variablen Verweis zugreift, wenn Sie ausdrücklich anders angegeben.Die = Element angibt, ob der Hauptteil der Lambda-Ausdruck alle erfasste Variablen Wert zugreift, wenn Sie ausdrücklich anders angegeben.Beispielsweise, wenn der Hauptteil eines Lambda-Ausdrucks externe Variable zugreift total durch einen Verweis und externe Variable factor Wert, dann die folgenden Capture-Klauseln sind gleichwertig:
[&total, factor]
[&, factor]
[=, &total]
Sie können die Lambda-Ausdrücke in den Körper der Methode einer Klasse.Übergeben Sie die this Zeiger auf der Capture-Klausel, um den Zugriff auf die Methoden und Datenmember der einschließenden Klasse zu ermöglichen.Ein Beispiel für die Verwendung von Lambda-Ausdruck mit Klassenmethoden, finden Sie unter Beispiel: verwenden einen Lambda-Ausdruck in einer Methode im Thema Beispiele für Lambda-Ausdrücke.
Parameterliste
Die Parameterliste für einen Lambda-Ausdruck ähnelt die Parameterliste für eine Funktion mit den folgenden Ausnahmen:
Die Parameterliste kann keine Standardargumente haben.
Die Parameterliste kann keine Argumentliste mit variabler Länge haben.
Die Parameterliste kann nicht Parameter Unbenannt haben.
Ein Lambda-Ausdruck kann ein anderes Lambdaausdruck als Argument in Anspruch nehmen.Weitere Informationen finden Sie unter Higher-Order Lambda-Ausdrücke im Thema Beispiele für Lambda-Ausdrücke.
Die Parameterliste für einen Lambda-Ausdruck ist optional.Sie können die Liste der Parameter auslassen, wenn Sie Argumente nicht an den Lambda-Ausdruck übergeben, und Sie nicht bieten die mutable-specification, exception-specification, und lambda-return-type-clause Elemente.Das folgende Beispiel zeigt einen Lambda-Ausdruck, der Liste die Parameter fehlt:
// lambda_parameter_list.cpp
int main()
{
int x = 4;
int y = 5;
int z = [=] { return x + y; }();
}
Änderbare Spezifikation
Das änderbaren Spezifikation Teil ermöglicht die Stelle eines Lambda-Ausdrucks Variablen zu ändern, die vom Wert erfasst werden.Im vorhergehenden Beispiel wird die mutable Schlüsselwort so, dass der Textkörper des Lambda-Ausdrucks seine Kopien der externen Variablen ändern kann x und y, die der Lambda-Ausdruck als Wert erfasst.Da der Lambda-Ausdruck Variablen erfasst x und y Wert, ihre Werte bleiben 1 nach dem Aufruf von generate_n.
Ausnahmespezifikation
Sie können die throw() Ausnahmespezifikation an, dass ein Lambda-Ausdruck keine Ausnahmen auslöst.Wie mit regelmäßigen Funktionen der Visual C++-Compiler eine Warnung generiert C4297 erklärt ein Lambda-Ausdruck der throw() Ausnahmespezifikation und der Lambda-Nachrichtentext löst eine Ausnahme auf, wie im folgenden Beispiel gezeigt:
// throw_lambda_expression.cpp
int main() // C4297 expected
{
[]() throw() { throw 5; }();
}
Weitere Informationen zu Ausnahmespezifikationen finden Sie unter Ausnahmespezifikation.
Rückgabetyp
Der Rückgabetyp Teil einen Lambda-Ausdruck ähnelt den Rückgabetyp Teil eine normale Methode oder Funktion.Jedoch der Rückgabetyp folgt der Parameterliste und Sie müssen -> vor dem Rückgabetyp.
Sie können den Rückgabetyp Teil einen Lambda-Ausdruck auslassen, wenn der Lambda-Nachrichtentext eine einzige return-Anweisung enthält oder der Lambda-Ausdruck keinen Wert zurück.Wenn der Lambda-Nachrichtentext aus einem einzigen return-Anweisung besteht, deduces der Compiler den Rückgabetyp vom Typ des Ausdrucks zurück.Andernfalls deduces der Compiler den Rückgabetyp sein void.
Ein Lambda-Ausdruck kann ein anderes Lambda-Ausdruck als ihren Rückgabewert erzeugen.Weitere Informationen finden Sie unter Higher-Order Lambda-Ausdrücke im Thema Beispiele für Lambda-Ausdrücke.
Lambda-Text
Der Lambda-Körperteil einen Lambda-Ausdruck kann alles enthalten, das der Körper einer normalen Methode oder Funktion enthalten kann.Der Hauptteil einer normalen Funktion und einen Lambda-Ausdruck kann die folgenden Typen von Variablen zugreifen:
Parameter
Lokal deklarierte Variablen
Datenmember der Klasse (wenn innerhalb einer Klasse deklariert wird)
Jede Variable, die statischen Speicher Dauer (z. B. globale Variablen)
Darüber hinaus kann ein Lambda-Ausdruck Variablen zugreifen, die sie aus den einschließenden Gültigkeitsbereich erfasst.Eine Variable ist explizit erfasst erscheint in der Capture-Klausel der Lambda-Ausdruck.Andernfalls die Variable ist implizit erfasst.Der Hauptteil der Lambda-Ausdruck verwendet den Standard-Capture-Modus zu Zugriff-Variablen, die implizit erfasst werden.
Die lambda_parameter_list.cpp Beispiel implizit erfasst die lokalen Variablen x und y Wert.Das folgende Beispiel enthält einen Lambda-Ausdruck, der die Variable explizit erfasst n durch einen Wert und implizit erfasst die Variable m als Verweis:
// 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;
}
In diesem Beispiel gibt Folgendes an der Konsole:
5
0
Da die Variable n vom Wert, der Wert bleibt erfasst 0 nach dem Aufruf der Lambda-Ausdruck.
Obwohl ein Lambda-Ausdruck nur Variablen, die automatische Speicherung Dauer haben erfassen kann, können Sie Variablen verwenden, die statischen Speicher Dauer im Textkörper des Lambda-Ausdruck.Im folgenden Beispiel wird die generate -Funktion und ein Lambda-Ausdruck zuweisen ein Werts für jedes Element in ein vector Objekt.Der Lambda-Ausdruck ändert die statische Variable den Wert des nächsten Elements generieren.
// 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++; });
}
Weitere Informationen zu den generate funktionieren, finden Sie unter Generieren.