Hvorfor Lambda Expression?
Overvej følgende udsagn:
int myInt = 52;Her er myInt en identifikator, en værdi. 52 er en bogstavelig, en værdi. I dag er det muligt at kode en funktion specielt og placere den i positionen 52. En sådan funktion kaldes et lambda-udtryk. Overvej også følgende korte program:
#omfatteved hjælp af namespace std;
int fn (int par)
int svar = par + 3;
returnere svar
int main ()
fn (5);
returnere 0;
I dag er det muligt at kode en funktion specielt og placere den i positionen af argumentet 5, for funktionsopkaldet, fn (5). En sådan funktion kaldes et lambda-udtryk. Lambda-udtrykket (funktionen) i denne position er en værdi.
Enhver bogstavelig undtagen strengen bogstavelig er en værdi. Lambda-udtrykket er et specielt funktionsdesign, der passer til en bogstavelig kode. Det er en anonym (unavngiven) funktion. Denne artikel forklarer det nye C ++ primære udtryk, kaldet lambda-udtrykket. Grundlæggende viden i C ++ er et krav for at forstå denne artikel.
Artikelindhold
- Illustration af Lambda Expression
- Dele af Lambda Expression
- Optager
- Klassisk Callback Function Scheme med Lambda Expression
- Den bageste-retur-type
- Lukning
- Konklusion
Illustration af Lambda Expression
I det følgende program tildeles en funktion, som er et lambda-udtryk, en variabel:
#omfatteved hjælp af namespace std;
auto fn = [] (int param)
int svar = param + 3;
returnere svar
;
int main ()
auto variab = fn (2);
cout << variab << '\n';
returnere 0;
Outputtet er:
5Uden for hovedfunktionen () er der variablen, fn. Dens type er automatisk. Auto i denne situation betyder, at den faktiske type, såsom int eller float, bestemmes af den rette operand af tildelingsoperatøren (=). Til højre for opgaveoperatøren er et lambda-udtryk. Et lambda-udtryk er en funktion uden den foregående returtype. Bemærk brugen og placeringen af de firkantede parenteser, []. Funktionen returnerer 5, en int, som bestemmer typen for fn.
I hovedfunktionen () er der udsagnet:
auto variab = fn (2);Dette betyder, at fn uden for hoved () ender som identifikator for en funktion. Dens implicitte parametre er dem for lambda-udtrykket. Typen for variab er auto.
Bemærk, at lambda-udtrykket ender med et semikolon, ligesom definitionen af klasse eller struktur, ender med et semikolon.
I det følgende program er en funktion, som er et lambda-udtryk, der returnerer værdien 5, et argument til en anden funktion:
#omfatteved hjælp af namespace std;
ugyldigt otherfn (int no1, int (* ptr) (int))
int no2 = (* ptr) (2);
cout << no1 << " << no2 << '\n';
int main ()
otherfn (4, [] (int param)
int svar = param + 3;
returnere svar
);
returnere 0;
Outputtet er:
4 5Der er to funktioner her, lambda-udtrykket og den andenfn () -funktion. Lambda-udtrykket er det andet argument for den andenfn (), kaldet main (). Bemærk, at lambda-funktionen (udtryk) ikke ender med semikolon i dette opkald, fordi det her er et argument (ikke en enkeltstående funktion).
Lambda-funktionsparameteren i definitionen af den andenfn () -funktion er en markør til en funktion. Markøren har navnet ptr. Navnet, ptr, bruges i definitionen af otherfn () til at kalde lambda-funktionen.
Erklæringen,
int no2 = (* ptr) (2);I definitionen otherfn () kalder den lambda-funktionen med et argument på 2. Returværdien af opkaldet "(* ptr) (2)" fra lambda-funktionen tildeles nr. 2.
Ovenstående program viser også, hvordan lambda-funktionen kan bruges i C ++ callback-funktionsskemaet.
Dele af Lambda Expression
Dele af en typisk lambda-funktion er som følger:
[] ()- [] er fangstklausulen. Det kan have genstande.
- () er til parameterlisten.
- er til funktionskroppen. Hvis funktionen står alene, skal den ende med et semikolon.
Optager
Lambda-funktionsdefinitionen kan tildeles en variabel eller bruges som argument til et andet funktionsopkald. Definitionen for et sådant funktionsopkald skal have som parameter en markør til en funktion svarende til lambdafunktionsdefinitionen.
Lambda-funktionsdefinitionen er forskellig fra den normale funktionsdefinition. Den kan tildeles en variabel i det globale omfang; denne funktion-tildelt-til-variabel kan også kodes i en anden funktion. Når den er tildelt en global scope-variabel, kan dens krop se andre variabler i den globale scope. Når den tildeles en variabel inde i en normal funktionsdefinition, kan dens krop kun se andre variabler i funktionsomfanget med hjælp af capture-klausulen, [].
Capture-klausulen [], også kendt som lambda-introduceren, tillader variabler, der skal sendes fra det omgivende (funktions) omfang ind i lambda-ekspressionens funktionslegeme. Lambda-ekspressionens funktionslegeme siges at fange variablen, når den modtager objektet. Uden capture-klausulen [] kan en variabel ikke sendes fra det omgivende omfang til lambda-ekspressionens funktionslegeme. Det følgende program illustrerer dette med det vigtigste () funktionsomfang som det omgivende omfang:
#omfatteved hjælp af namespace std;
int main ()
int id = 5;
auto fn = [id] ()
cout << id << '\n';
;
fn ();
returnere 0;
Outputtet er 5. Uden navnet, id, inden i [], ville lambda-udtrykket ikke have set variablen id for hovedfunktionsområdet ().
Optagelse med reference
Ovenstående eksempel på anvendelse af capture-klausulen er capture efter værdi (se detaljer nedenfor). Ved optagelse ved henvisning placeres (lagring) af variablen, f.eks.g., id ovenfor, af det omgivende omfang, stilles til rådighed inde i lambda-funktionskroppen. Så ændring af værdien af variablen inde i lambda-funktionskroppen vil ændre værdien af den samme variabel i det omgivende omfang. Hver variabel, der gentages i capture-klausulen, er forud for ampersand (&) for at opnå dette. Følgende program illustrerer dette:
#omfatteved hjælp af namespace std;
int main ()
int id = 5; flyde ft = 2.3; char ch = 'A';
auto fn = [& id, & ft, & ch] ()
id = 6; ft = 3.4; ch = 'B';
;
fn ();
cout << id << ", " << ft << ", " << ch << '\n';
returnere 0;
Outputtet er:
6, 3.4, BBekræftelse af, at variabelnavne inde i lambda-ekspressionens funktionslegeme er for de samme variabler uden for lambda-udtrykket.
Optagelse efter værdi
Ved optagelse efter værdi stilles en kopi af variabelens placering, af det omgivende omfang til rådighed inde i lambdafunktionslegemet. Selvom variablen inde i lambdafunktionslegemet er en kopi, kan dens værdi ikke ændres inden i kroppen fra nu af. For at opnå optagelse efter værdi går hver variabel, der gentages i capture-klausulen, ikke forud for noget. Følgende program illustrerer dette:
#omfatteved hjælp af namespace std;
int main ()
int id = 5; flyde 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';
returnere 0;
Outputtet er:
5, 2.3, A6, 3.4, B
Hvis kommentarindikatoren fjernes, kompileres ikke programmet. Compileren udsender en fejlmeddelelse om, at variablerne i funktionskroppens definition af lambda-udtrykket ikke kan ændres. Selvom variablerne ikke kan ændres inden for lambda-funktionen, kan de ændres uden for lambda-funktionen, som ovenstående programs output viser.
Blanding af optagelser
Optagelse med reference og optagelse efter værdi kan blandes, som det følgende program viser:
#omfatteved hjælp af namespace std;
int main ()
int id = 5; flyde ft = 2.3; char ch = 'A'; bool bl = sand;
auto fn = [id, ft, & ch, & bl] ()
ch = 'B'; bl = falsk;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
returnere 0;
Outputtet er:
5, 2.3, B, 0Når alle er fanget, er de som reference:
Hvis alle variabler, der skal fanges, fanges ved henvisning, er det kun en &, der er tilstrækkelig i fangstklausulen. Følgende program illustrerer dette:
#omfatteved hjælp af namespace std;
int main ()
int id = 5; flyde ft = 2.3; char ch = 'A'; bool bl = sand;
auto fn = [&] ()
id = 6; ft = 3.4; ch = 'B'; bl = falsk;
;
fn ();
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
returnere 0;
Outputtet er:
6, 3.4, B, 0Hvis nogle variabler skal fanges med reference og andre efter værdi, repræsenterer en & alle referencer, og resten vil hver ikke blive forud for noget, som det følgende program viser:
ved hjælp af namespace std;int main ()
int id = 5; flyde ft = 2.3; char ch = 'A'; bool bl = sandt;
auto fn = [&, id, ft] ()
ch = 'B'; bl = falsk;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
returnere 0;
Outputtet er:
5, 2.3, B, 0Bemærk at & alene (i.e., & ikke efterfulgt af en identifikator) skal være det første tegn i capture-klausulen.
Når alle er fanget, er de efter værdi:
Hvis alle variabler, der skal fanges, skal fanges efter værdi, er bare en = tilstrækkelig i fangstklausulen. Følgende program illustrerer dette:
#omfatteved hjælp af namespace std;
int main ()
int id = 5; flyde ft = 2.3; char ch = 'A'; bool bl = sand;
auto fn = [=] ()
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
returnere 0;
Outputtet er:
5, 2.3, A, 1Bemærk: = er skrivebeskyttet, lige nu.
Hvis nogle variabler skal fanges af værdi og andre som reference, repræsenterer en = alle de skrivebeskyttede kopierede variabler, og resten har hver &, som det følgende program viser:
#omfatteved hjælp af namespace std;
int main ()
int id = 5; flyde ft = 2.3; char ch = 'A'; bool bl = sand;
auto fn = [=, & ch, & bl] ()
ch = 'B'; bl = falsk;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
returnere 0;
Outputtet er:
5, 2.3, B, 0Bemærk, at = alene skal være det første tegn i capture-klausulen.
Klassisk Callback Function Scheme med Lambda Expression
Følgende program viser, hvordan et klassisk tilbagekaldsfunktionsskema kan udføres med lambda-udtrykket:
#omfatteved hjælp af namespace std;
char * output;
auto cba = [] (char out [])
output = ud;
;
void principalFunc (char input [], void (* pt) (char []))
(* pt) (input);
cout<<"for principal function"<<'\n';
ugyldigt fn ()
cout<<"Now"<<'\n';
int main ()
char input [] = "til tilbagekaldsfunktion";
principalFunc (input, cba);
fn ();
cout<