Hvorfor Lambda Expression?
Tenk på følgende utsagn:
int myInt = 52;Her er myInt en identifikator, en verdi. 52 er en bokstavelig, en verdi. I dag er det mulig å kode en funksjon spesielt og sette den i posisjonen 52. En slik funksjon kalles et lambdauttrykk. Tenk også på følgende korte program:
#inkluderebruker navneområde std;
int fn (int par)
int svar = par + 3;
returnere svar;
int main ()
fn (5);
retur 0;
I dag er det mulig å kode en funksjon spesielt og sette den i posisjonen til argumentet til 5, for funksjonsanropet, fn (5). En slik funksjon kalles et lambdauttrykk. Lambdauttrykket (funksjonen) i den posisjonen er en verdi.
Enhver bokstavelig, bortsett fra strengen, er en verdi. Lambda-uttrykket er en spesiell funksjonsdesign som passer som en bokstavelig kode. Det er en anonym (ikke navngitt) funksjon. Denne artikkelen forklarer det nye C ++ primære uttrykket, kalt lambdauttrykket. Grunnleggende kunnskap i C ++ er et krav for å forstå denne artikkelen.
Artikkelinnhold
- Illustrasjon av Lambda Expression
- Deler av Lambda Expression
- Fanger
- Klassisk tilbakeringingsfunksjonsskjema med Lambda-uttrykk
- Den etterfølgende retur-typen
- Lukking
- Konklusjon
Illustrasjon av Lambda Expression
I det følgende programmet er en funksjon, som er et lambdauttrykk, tilordnet en variabel:
#inkluderebruker navneområde std;
auto fn = [] (int param)
int svar = param + 3;
returnere svar;
;
int main ()
auto variab = fn (2);
cout << variab << '\n';
retur 0;
Utgangen er:
5Utenfor hovedfunksjonen () er det variabelen, fn. Dens type er automatisk. Auto i denne situasjonen betyr at den faktiske typen, for eksempel int eller float, bestemmes av den rette operanden til oppdragsoperatøren (=). Til høyre for oppdragsoperatøren er et lambdauttrykk. Et lambdauttrykk er en funksjon uten forrige returtype. Legg merke til bruken og plasseringen av hakeparentesene, []. Funksjonen returnerer 5, en int, som vil bestemme typen for fn.
I hovedfunksjonen () er det utsagnet:
auto variab = fn (2);Dette betyr at fn utenfor main () ender som identifikator for en funksjon. Dens implisitte parametere er de for lambda-uttrykket. Typen for variab er auto.
Merk at lambdauttrykket ender med semikolon, akkurat som klasse- eller strukturdefinisjonen, ender med semikolon.
I det følgende programmet er en funksjon, som er et lambdauttrykk som returnerer verdien 5, et argument til en annen funksjon:
#inkluderebruker navneområde std;
ugyldig 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;
);
retur 0;
Utgangen er:
4 5Det er to funksjoner her, lambdauttrykket og den andrefn () -funksjonen. Lambdauttrykket er det andre argumentet til otherfn (), kalt main (). Merk at lambda-funksjonen (uttrykk) ikke ender med semikolon i denne samtalen, fordi det her er et argument (ikke en frittstående funksjon).
Lambda-funksjonsparameteren i definisjonen av otherfn () -funksjonen er en peker til en funksjon. Pekeren har navnet, ptr. Navnet, ptr, brukes i den andrefn () definisjonen for å kalle lambda-funksjonen.
Uttalelsen,
int no2 = (* ptr) (2);I otherfn () -definisjonen kaller den lambdafunksjonen med argumentet 2. Returverdien for samtalen, "(* ptr) (2)" fra lambda-funksjonen, er tildelt nr. 2.
Ovennevnte program viser også hvordan lambda-funksjonen kan brukes i C ++ tilbakekallingsfunksjonen.
Deler av Lambda Expression
Delene av en typisk lambda-funksjon er som følger:
[] ()- [] er fangstklausulen. Det kan ha gjenstander.
- () er for parameterlisten.
- er for funksjonsdelen. Hvis funksjonen står alene, bør den ende med semikolon.
Fanger
Lambda-funksjonsdefinisjonen kan tilordnes en variabel eller brukes som argument for en annen funksjonsanrop. Definisjonen for en slik funksjonsanrop skal ha som parameter en peker til en funksjon som tilsvarer lambdafunksjonens definisjon.
Lambda-funksjonsdefinisjonen er forskjellig fra normal funksjonsdefinisjon. Den kan tilordnes en variabel i det globale omfanget; denne funksjonen-tilordnet-til-variabelen kan også kodes i en annen funksjon. Når den er tildelt en global variabel, kan kroppen se andre variabler i det globale omfanget. Når den er tildelt en variabel i en normal funksjonsdefinisjon, kan kroppen se andre variabler i funksjonsomfanget bare med fangstklausulens hjelp, [].
Fangsparagrafen [], også kjent som lambda-introdusenten, lar variabler sendes fra det omgivende (funksjons) omfanget til lambda-uttrykkets funksjonslegeme. Lambdauttrykkets funksjonskropp sies å fange variabelen når den mottar objektet. Uten fangstklausulen [] kan en variabel ikke sendes fra det omgivende omfanget inn i lambdauttrykkets funksjonslegeme. Følgende program illustrerer dette, med hovedfunksjonen (), som det omliggende omfanget:
#inkluderebruker navneområde std;
int main ()
int id = 5;
auto fn = [id] ()
cout << id << '\n';
;
fn ();
retur 0;
Resultatet er 5. Uten navnet, id, inne i [], ville ikke lambdauttrykket sett variabelen id til hovedfunksjonen ().
Fange etter referanse
Ovennevnte bruk av fangstklausulen er å fange etter verdi (se detaljer nedenfor). I fangst med referanse, plasseringen (lagring) av variabelen, f.eks.g., id over, av det omkringliggende omfanget, blir gjort tilgjengelig inne i lambdafunksjonskroppen. Så hvis du endrer verdien på variabelen i lambdafunksjonens kropp, endres verdien på den samme variabelen i det omliggende omfanget. Hver variabel som er gjentatt i fangstklausulen, er foran med ampersand (&) for å oppnå dette. Følgende program illustrerer dette:
#inkluderebruker navneområde std;
int main ()
int id = 5; flyte ft = 2.3; char ch = 'A';
auto fn = [& id, & ft, & ch] ()
id = 6; ft = 3.4; ch = 'B';
;
fn ();
cout << id << ", " << ft << ", " << ch << '\n';
retur 0;
Utgangen er:
6, 3.4, BBekrefter at variabelnavnene inne i lambdauttrykkets funksjonslegeme er for de samme variablene utenfor lambdauttrykket.
Fange etter verdi
Ved å fange etter verdi blir en kopi av variabelens plassering, av det omkringliggende omfanget, tilgjengelig i lambdafunksjonens kropp. Selv om variabelen inne i lambdafunksjonen er en kopi, kan verdien ikke endres i kroppen fra nå av. For å oppnå fangst etter verdi, går ikke hver variabel som er gjentatt i fangstklausulen, foran noe. Følgende program illustrerer dette:
#inkluderebruker navneområde std;
int main ()
int id = 5; flyte 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';
retur 0;
Utgangen er:
5, 2.3, A6, 3.4, B
Hvis kommentarindikatoren blir fjernet, kompileres ikke programmet. Kompilatoren vil gi en feilmelding om at variablene i funksjonslegemets definisjon av lambdauttrykket ikke kan endres. Selv om variablene ikke kan endres i lambdafunksjonen, kan de endres utenfor lambdafunksjonen, som programmet ovenfor viser.
Blanding av fanger
Fange med referanse og fange etter verdi kan blandes, som følgende program viser:
#inkluderebruker navneområde std;
int main ()
int id = 5; flyte ft = 2.3; char ch = 'A'; bool bl = sant;
auto fn = [id, ft, & ch, & bl] ()
ch = 'B'; bl = falsk;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
retur 0;
Utgangen er:
5, 2.3, B, 0Når alle er fanget, blir de referert:
Hvis alle variablene som skal fanges, blir fanget opp ved referanse, er det bare én & som er tilstrekkelig i fangstklausulen. Følgende program illustrerer dette:
#inkluderebruker navneområde std;
int main ()
int id = 5; flyte ft = 2.3; char ch = 'A'; bool bl = sant;
auto fn = [&] ()
id = 6; ft = 3.4; ch = 'B'; bl = falsk;
;
fn ();
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
retur 0;
Utgangen er:
6, 3.4, B, 0Hvis noen variabler skal fanges med referanse og andre etter verdi, vil en & representere alle referansene, og resten vil hver ikke bli innledet av noe, som følgende program viser:
bruker navneområde std;int main ()
int id = 5; flyte ft = 2.3; char ch = 'A'; bool bl = sant;
auto fn = [&, id, ft] ()
ch = 'B'; bl = falsk;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
retur 0;
Utgangen er:
5, 2.3, B, 0Legg merke til at & alene (i.e., & ikke etterfulgt av en identifikator) må være det første tegnet i fangstklausulen.
Når alle er fanget, er de etter verdi:
Hvis alle variablene som skal fanges, skal fanges opp av verdi, vil bare en = være tilstrekkelig i fangstklausulen. Følgende program illustrerer dette:
#inkluderebruker navneområde std;
int main ()
int id = 5; flyte ft = 2.3; char ch = 'A'; bool bl = sant;
auto fn = [=] ()
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
retur 0;
Utgangen er:
5, 2.3, A, 1Merk: = er skrivebeskyttet, per nå.
Hvis noen variabler skal fanges opp av verdi og andre som referanse, vil en = representere alle de skrivebeskyttede kopierte variablene, og resten vil hver ha &, som følgende program viser:
#inkluderebruker navneområde std;
int main ()
int id = 5; flyte ft = 2.3; char ch = 'A'; bool bl = sant;
auto fn = [=, & ch, & bl] ()
ch = 'B'; bl = falsk;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
retur 0;
Utgangen er:
5, 2.3, B, 0Merk at = alene må være det første tegnet i fangstklausulen.
Klassisk tilbakeringingsfunksjonsskjema med Lambda-uttrykk
Følgende program viser hvordan en klassisk tilbakekallingsfunksjon kan gjøres med lambda-uttrykket:
#inkluderebruker navneområde std;
char * utgang;
auto cba = [] (char out [])
utgang = ut;
;
void principalFunc (char input [], void (* pt) (char []))
(* pt) (inngang);
cout<<"for principal function"<<'\n';
ugyldig fn ()
cout<<"Now"<<'\n';
int main ()
char input [] = "for tilbakeringingsfunksjon";
principalFunc (input, cba);
fn ();
cout<