Heim > Artikel > Backend-Entwicklung > Eine kurze Analyse von Lambda-Ausdrücken und neuen Funktionen von C++11
Einführung in Lambda
Programmierer, die mit Python vertraut sind, sollten mit Lambda vertraut sein. Einfach ausgedrückt ist ein Lambda ein anonym aufrufbarer Codeblock. Im neuen C++11-Standard hat Lambda das folgende Format:
[capture list] (parameter list) -> return type { function body }
Wie Sie sehen können, besteht es aus vier Komponenten:
1. Capture-Liste : Erfassungsliste
2.Parameterliste: Parameterliste
3.Rückgabetyp: Rückgabetyp
4.Funktionskörper: Ausführung Code
wobei die Parameterliste und der Rückgabetyp ignoriert werden können.
Nachfolgend sehen wir uns ein paar einfache Beispiele an:
auto f1 = [] { return 1; }; auto f2 = [] () { return 2; }; cout<<f1()<<'\t'<<f2()<<endl;
Capture-Liste
Die Capture-Liste in Lambda kann beide Werte erfassen und Referenzen können erfasst werden.
Capture-Wert:
int test_data[] = {1, 5, 9, 7, 3, 19, 13, 17}; int border = 8; auto f3 = [border](const int &i){ if(i > border) cout<<i<<'\t'; }; for_each(begin(test_data), end(test_data), f3); cout<<endl;
Capture-Referenz:
auto f4 = [&border](const int &i){ if(i > border) cout<<i<<'\t'; }; border = 6; for_each(begin(test_data), end(test_data), f4); cout<<endl;
Wie aus der Ausgabe ersichtlich ist, in Lambda Die effektive Grenze ist die modifizierte 6, was bestätigt, dass die Erfassung tatsächlich eine Referenz ist.
Es ist zu beachten, dass beim Erfassen einer Referenz sichergestellt werden muss, dass diese Referenz beim Aufruf des Lambda noch gültig ist.
Die Erfassungsliste kann auch implizite Erfassung verwenden, wodurch der Compiler durch den Lambda-Ausführungscode bestimmen kann, welche lokalen Variablen erfasst werden müssen.
Implizite Erfassung kann Werte, Referenzen oder eine Mischung aus beidem erfassen:
char space = ' '; auto f5 = [=](const int &i){ if(i > border) cout<<i<<'\t'; }; auto f6 = [&](const int &i){ if(i > border) cout<<i<<'\t'; }; auto f7 = [&, space](const int &i){ if(i > border) cout<<i<<space; }; border = 0; for_each(begin(test_data), end(test_data), f5); cout<<endl; for_each(begin(test_data), end(test_data), f6); cout<<endl; for_each(begin(test_data), end(test_data), f7); cout<<endl;
Die hier von f7 verwendete Mischform kann als „außer Leerzeichen“ gelesen werden Capture-Wert „Abgesehen davon erfassen alle anderen Variablen Referenzen“.
Variables Lambda
Wenn das Lambda den Wert der vom Wert erfassten Variablen ändern muss, muss das veränderliche Schlüsselwort zum Lambda hinzugefügt werden. Andernfalls kommt es zu Kompilierungsfehlern.
auto f8 = [&, space](const int &i) mutable { if(i > border) {cout<<i<<space; space='\t';} }; for_each(begin(test_data), end(test_data), f8); cout<<endl; cout<<1<<space<<2<<endl;
Wie aus der Ausgabe ersichtlich ist, wurde der Wert von Leerzeichen in Lambda F8 nach dem ersten Aufruf in das Tabulatorzeichen Tab umgewandelt; ist immer noch ein Leerzeichen.
Rückgabetyp
Der Rückgabetyp von Lambda übernimmt die Tail-Return-Type-Methode. Allgemein:
1. Wenn das Lambda nur eine Rückgabeanweisung enthält, kann der Compiler auf seinen Rückgabetyp schließen und der Rückgabetyp muss nicht explizit angegeben werden
2. Andernfalls geht der Compiler davon aus, dass Lambda void zurückgibt und eine Funktion, die void zurückgibt, keinen bestimmten Wert zurückgeben kann. Dies ist in den meisten Fällen ein Widerspruch, daher muss der Rückgabetyp explizit angegeben werden.
Nach tatsächlichen Tests ist der aktuelle G++-Compiler jedoch intelligenter: Für Punkt 2 besteht derzeit keine Notwendigkeit, solange der Compiler den Rückgabetyp der Funktion aus dem Lambda-Funktionskörper ableiten kann explizit Formel gibt den Rückgabetyp an, zum Beispiel:
auto f9 = [](const int i){if(i % 3) return i * 3; else return i;}; transform(begin(test_data), end(test_data), begin(test_data), f9); border = 0; for_each(begin(test_data), end(test_data), f6); cout<<endl;
Es gibt mehrere Rückgabeanweisungen im Lambda-Codeblock und es gibt auch if/else-Anweisungen, der Compiler kann dies jedoch Basierend auf der Rückgabeanweisung sollte der Rückgabewert vom Typ int sein, sodass der nachfolgende Rückgabetyp weggelassen werden kann.
Im folgenden Formular muss der Rückgabetyp jedoch explizit angegeben werden, da der Compiler beim Ableiten des Rückgabetyps Inkonsistenzen festgestellt hat:
auto f10 = [](const int i) -> double {if(i % 5) return i * 5.0; else return i;}; transform(begin(test_data), end(test_data), begin(test_data), f10); for_each(begin(test_data), end(test_data), f6); cout<<endl;
Zusammenfassung
1. Lambda-Ausdrucksform: [Erfassungsliste] (Parameterliste) -> Rückgabetyp { Funktionskörper }, wobei Parameterliste und Rückgabetyp weggelassen werden können.
2. Die Erfassungsliste kann den Wert [val] oder die Referenz [&ref] erfassen.
3. Die Erfassungsliste kann auch implizit lokale Variablen erfassen. Es gibt auch zwei Methoden zum Erfassen von Werten [=] und zum Erfassen von Referenzen [&]. gemischt [&, val] Oder [=, &ref].
4. Wenn Lambda den erfassten Wert ändern muss, muss das veränderbare Schlüsselwort hinzugefügt werden.
4. Wenn Lambda den Rückgabewerttyp nicht automatisch ableiten kann, muss er explizit durch Anhängen des Rückgabetyps angegeben werden.
Das Obige ist der gesamte Inhalt des Lambda-Ausdrucks, einer neuen Funktion von C++11. Ich hoffe, dass dieser Artikel für alle beim Erlernen von C++ hilfreich sein wird.
Weitere Artikel zu Lambda-Ausdrücken, die die neuen Funktionen von C++11 kurz analysieren, finden Sie auf der chinesischen PHP-Website!