Prečo lambda výraz?
Zvážte nasledujúce vyhlásenie:
int myInt = 52;MyInt je identifikátor, hodnota l. 52 je literál, prvalue. Dnes je možné špeciálne kódovať funkciu a umiestniť ju na pozíciu 52. Takáto funkcia sa nazýva výraz lambda. Zvážte tiež nasledujúci krátky program:
#includepomocou namespace std;
int fn (int par)
int odpoveď = par + 3;
spätná odpoveď;
int main ()
fn (5);
návrat 0;
Dnes je možné špeciálne kódovať funkciu a umiestniť ju do polohy argumentu 5, volania funkcie, fn (5). Takáto funkcia sa nazýva výraz lambda. Výraz (funkcia) lambda v tejto polohe je prvalue.
Akýkoľvek literál okrem reťazcového literálu je prvalue. Výraz lambda je návrh špeciálnej funkcie, ktorý by sa hodil ako literál v kóde. Je to anonymná (nepomenovaná) funkcia. Tento článok vysvetľuje nový primárny výraz C ++, ktorý sa nazýva výraz lambda. Na pochopenie tohto článku sú potrebné základné znalosti v jazyku C ++.
Obsah článku
- Ilustrácia lambda výrazu
- Časti výrazu lambda
- Zachytáva
- Schéma klasického spätného volania s výrazom lambda
- Typ s koncovým návratom
- Uzavretie
- Záver
Ilustrácia lambda výrazu
V nasledujúcom programe je k premennej priradená funkcia, ktorá je výrazom lambda
#includepomocou namespace std;
auto fn = [] (int param)
int odpoveď = param + 3;
spätná odpoveď;
;
int main ()
automatická premenná = fn (2);
cout << variab << '\n';
návrat 0;
Výstup je:
5Mimo funkcie main () je premenná fn. Jeho typ je auto. Auto v tejto situácii znamená, že skutočný typ, napríklad int alebo float, je určený pravým operandom operátora priradenia (=). Na pravej strane operátora priradenia je výraz lambda. Výraz lambda je funkcia bez predchádzajúceho návratového typu. Všimnite si použitie a polohu hranatých zátvoriek, []. Funkcia vráti 5, int, ktoré určia typ pre fn.
Vo funkcii main () je príkaz:
automatická premenná = fn (2);To znamená, že fn mimo main () končí ako identifikátor funkcie. Jeho implicitné parametre sú parametre výrazu lambda. Typ pre premennú je auto.
Upozorňujeme, že výraz lambda končí bodkočiarkou, rovnako ako definícia triedy alebo štruktúry, končí bodkočiarkou.
V nasledujúcom programe je funkcia, ktorá je výrazom lambda vracajúcim hodnotu 5, argumentom pre inú funkciu:
#includepomocou namespace std;
void otherfn (int no1, int (* ptr) (int))
int no2 = (* ptr) (2);
cout << no1 << " << no2 << '\n';
int main ()
otherfn (4, [] (int param)
int odpoveď = param + 3;
spätná odpoveď;
);
návrat 0;
Výstup je:
4 5Existujú tu dve funkcie, výraz lambda a funkcia otherfn (). Výraz lambda je druhým argumentom otherfn (), ktorý sa volá main (). Upozorňujeme, že funkcia (výraz) lambda v tomto volaní nekončí bodkočiarkou, pretože tu ide o argument (nie samostatnú funkciu).
Parameter funkcie lambda v definícii funkcie otherfn () je ukazovateľ na funkciu. Ukazovateľ má názov, ptr. Názov ptr sa v definícii otherfn () používa na volanie funkcie lambda.
Výkaz,
int no2 = (* ptr) (2);V definícii otherfn () volá funkciu lambda s argumentom 2. Návratová hodnota hovoru „(* ptr) (2)“ z funkcie lambda je priradená číslu 2.
Vyššie uvedený program tiež ukazuje, ako je možné použiť funkciu lambda v schéme funkcií spätného volania C ++.
Časti výrazu lambda
Časti typickej funkcie lambda sú nasledovné:
[] ()- [] je doložka o zajatí. Môže obsahovať položky.
- () je pre zoznam parametrov.
- je pre telo funkcie. Ak je funkcia samostatne stojaca, mala by sa končiť bodkočiarkou.
Zachytáva
Definíciu funkcie lambda je možné priradiť k premennej alebo použiť ako argument na volanie inej funkcie. Definícia takéhoto volania funkcie by mala mať ako parameter, ukazovateľ na funkciu, zodpovedajúci definícii funkcie lambda.
Definícia funkcie lambda sa líši od definície normálnej funkcie. Môže byť priradený k premennej v globálnom rozsahu; túto funkciu priradenú k premennej je možné kódovať aj v rámci inej funkcie. Keď je priradený k premennej globálneho rozsahu, jej telo uvidí ďalšie premenné v globálnom rozsahu. Keď je priradená k premennej v rámci definície normálnej funkcie, jej telo vidí ďalšie premenné v rozsahu funkcie iba s pomocou doložky o zachytení, [].
Klauzula o zachytení [], známa tiež ako zavádzač lambda, umožňuje posielať premenné z okolitého (funkčného) rozsahu do tela funkcie výrazu lambda. Telo funkcie výrazu lambda údajne zachytí premennú, keď prijme objekt. Bez klauzuly o zachytení [] nie je možné poslať premennú z okolitého rozsahu do tela funkcie výrazu lambda. Nasledujúci program to ilustruje s rozsahom funkcií main () ako okolitým rozsahom:
#includepomocou namespace std;
int main ()
int id = 5;
auto fn = [id] ()
cout << id << '\n';
;
fn ();
návrat 0;
Výstup je 5. Bez názvu, id, vo vnútri [] by výraz lambda nevidel premennú id rozsahu funkcie main ().
Zachytávanie referenciou
Vyššie uvedené použitie klauzuly na zachytávanie je zachytávanie podľa hodnoty (podrobnosti nájdete nižšie). Pri zachytávaní pomocou referencie je umiestnenie (úložisko) premennej, napr.g., vyššie uvedené, okolitého rozsahu, je k dispozícii vo vnútri tela funkcie lambda. Takže zmena hodnoty premennej vo vnútri tela funkcie lambda zmení hodnotu tej istej premennej v okolitom rozsahu. Na dosiahnutie tejto hodnoty je pred každou premennou opakovanou v doložke capture ampersand (&). Nasledujúci program to ilustruje:
#includepomocou namespace std;
int main ()
int id = 5; float ft = 2.3; char ch = 'A';
auto fn = [& id, & ft, & ch] ()
id = 6; ft = 3.4; ch = 'B';
;
fn ();
cout << id << ", " << ft << ", " << ch << '\n';
návrat 0;
Výstup je:
6, 3.4, BPotvrdenie, že názvy premenných vo vnútri tela funkcie výrazu lambda sú pre rovnaké premenné mimo výrazu lambda.
Zachytávanie podľa hodnoty
Pri snímaní podľa hodnoty je vo vnútri tela funkcie lambda k dispozícii kópia umiestnenia premennej, obklopujúceho rozsahu. Aj keď premenná vo vnútri tela funkcie lambda je kópia, jej hodnotu už teraz nemožno vo vnútri tela meniť. Aby sa dosiahlo zachytenie podľa hodnoty, každej premennej opakovanej v doložke zachytenia nič nepredchádza. Nasledujúci program to ilustruje:
#includepomocou namespace std;
int main ()
int id = 5; float ft = 2.3; char ch = 'A';
auto fn = [id, ft, ch] ()
// id = 6; ft = 3.4; ch = 'B';
cout << id << ", " << ft << ", " << ch << '\n';
;
fn ();
id = 6; ft = 3.4; ch = 'B';
cout << id << ", " << ft << ", " << ch << '\n';
návrat 0;
Výstup je:
5, 2.3, A6, 3.4, B
Ak je indikátor komentára odstránený, program sa nezkompiluje. Kompilátor vydá chybové hlásenie, že premenné vo vnútri definície tela výrazu lambda nie je možné zmeniť. Aj keď premenné nie je možné meniť vo vnútri funkcie lambda, je možné ich meniť aj mimo funkcie lambda, ako ukazuje výstup vyššie uvedeného programu.
Mixing Captures
Zachytávanie pomocou referencie a zachytávanie podľa hodnoty je možné kombinovať, ako ukazuje nasledujúci program:
#includepomocou namespace std;
int main ()
int id = 5; float ft = 2.3; char ch = 'A'; bool bl = pravda;
auto fn = [id, ft, & ch, & bl] ()
ch = 'B'; bl = false;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
návrat 0;
Výstup je:
5, 2.3, B, 0Keď sú všetky zachytené, sú odkazom:
Ak sú všetky premenné, ktoré sa majú zachytiť, zachytené odkazom, potom v doložke zachytenia postačí iba jedna &. Nasledujúci program to ilustruje:
#includepomocou namespace std;
int main ()
int id = 5; float ft = 2.3; char ch = 'A'; bool bl = pravda;
auto fn = [&] ()
id = 6; ft = 3.4; ch = 'B'; bl = false;
;
fn ();
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
návrat 0;
Výstup je:
6, 3.4, B, 0Ak majú byť niektoré premenné zachytené pomocou referencie a iné podľa hodnoty, potom jedna & bude predstavovať všetky referencie a zvyšku nebude nič predchádzať, ako ukazuje nasledujúci program:
pomocou namespace std;int main ()
int id = 5; float ft = 2.3; char ch = 'A'; bool bl = pravda;
auto fn = [&, id, ft] ()
ch = 'B'; bl = false;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
návrat 0;
Výstup je:
5, 2.3, B, 0Všimnite si, že & sám (t.j.e., a za ktorým nenasleduje identifikátor) musí byť prvý znak v doložke zachytenia.
Keď sú všetky zachytené, sú podľa hodnoty:
Ak sa majú zachytiť všetky premenné, ktoré sa majú zachytiť podľa hodnoty, v klauzuli o zachytení postačí iba jedna =. Nasledujúci program to ilustruje:
#includepomocou namespace std;
int main ()
int id = 5; float ft = 2.3; char ch = 'A'; bool bl = pravda;
auto fn = [=] ()
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
návrat 0;
Výstup je:
5, 2.3, A, 1Poznámka: = je odteraz iba na čítanie.
Ak majú byť niektoré premenné zachytené hodnotou a iné odkazom, potom jedna = bude predstavovať všetky kopírované premenné iba na čítanie a zvyšok bude mať znak &, ako ukazuje nasledujúci program:
#includepomocou namespace std;
int main ()
int id = 5; float ft = 2.3; char ch = 'A'; bool bl = pravda;
auto fn = [=, & ch, & bl] ()
ch = 'B'; bl = false;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
návrat 0;
Výstup je:
5, 2.3, B, 0Všimnite si, že = sám musí byť prvým znakom v doložke zachytenia.
Schéma klasického spätného volania s výrazom lambda
Nasledujúci program ukazuje, ako je možné vykonať klasickú schému funkcie spätného volania s výrazom lambda:
#includepomocou namespace std;
char * výstup;
auto cba = [] (char out [])
výstup = von;
;
void principalFunc (char input [], void (* pt) (char []))
(* pt) (vstup);
cout<<"for principal function"<<'\n';
void fn ()
cout<<"Now"<<'\n';
int main ()
char input [] = "pre funkciu spätného volania";
principalFunc (vstup, cba);
fn ();
cout<