Lambda -uttrykk i C ++

Lambda Expressions C



Hvorfor Lambda -uttrykk?

Vurder følgende utsagn:

intminInt= 52;

Her er myInt en identifikator, en l -verdi. 52 er en bokstavelig verdi. I dag er det mulig å kode en funksjon spesielt og sette den i posisjon 52. En slik funksjon kalles et lambdauttrykk. Vurder også følgende korte program:







#inkludere

ved hjelp av navneområdetimer;

intfn(intgjennom)

{

intsvar=gjennom+ 3;

komme tilbakesvar;

}


inthoved-()

{

fn(5);



komme tilbake 0;

}

I dag er det mulig å kode en funksjon spesielt og sette den i posisjonen til argumentet til 5, til funksjonsanropet, fn (5). En slik funksjon kalles et lambda -uttrykk. Lambda -uttrykket (funksjon) i den posisjonen er en verdi.



Enhver bokstav bortsett fra strengen bokstavelig er en prverdi. Lambda -uttrykket er en spesiell funksjonsdesign som passer som bokstavelig talt i koden. Det er en anonym (ikke navngitt) funksjon. Denne artikkelen forklarer det nye C ++ - primære uttrykket, kalt lambda -uttrykket. Grunnleggende kunnskap i C ++ er et krav for å forstå denne artikkelen.



Artikkelinnhold

Illustrasjon av Lambda Expression

I det følgende programmet er en funksjon, som er et lambda -uttrykk, tilordnet en variabel:





#inkludere

ved hjelp av navneområdetimer;

autofn= [](intStoppe)

{

intsvar=Stoppe+ 3;

komme tilbakesvar;

};


inthoved-()

{

autovariab=fn(2);

koste <<variab<< ' n';


komme tilbake 0;

}

Utgangen er:

5

Utenfor hovedfunksjonen () er variabelen fn. Dens type er auto. Auto i denne situasjonen betyr at den faktiske typen, for eksempel int eller float, bestemmes av høyre operand til tildelingsoperatøren (=). Til høyre for oppdragsoperatøren er et lambda -uttrykk. Et lambda -uttrykk er en funksjon uten den foregående returtypen. Legg merke til bruken og plasseringen av de firkantede parentesene, []. Funksjonen returnerer 5, en int, som bestemmer typen for fn.



I hovedfunksjonen () er det utsagnet:

autovariab=fn(2);

Dette betyr at fn utenfor main () ender opp som identifikator for en funksjon. Dets implisitte parametere er de til lambda -uttrykket. Typen for variab er auto.

Vær oppmerksom på at lambda -uttrykket ender med et semikolon, akkurat som klasse- eller strukturdefinisjonen, slutter med et semikolon.

I det følgende programmet er en funksjon, som er et lambda -uttrykk som returnerer verdien til 5, et argument til en annen funksjon:

#inkludere

ved hjelp av navneområdetimer;

tomromannetfn(intno1,int (*ptr)(int))

{

intnr2= (*ptr)(2);

koste <<no1<< '' <<nr2<< ' n';

}


inthoved-()

{

annetfn(4,[](intStoppe)

{

intsvar=Stoppe+ 3;

komme tilbakesvar;

});


komme tilbake 0;
}

Utgangen er:

Fire fem

Det er to funksjoner her, lambda -uttrykket og den andrefn () -funksjonen. Lambda -uttrykket er det andre argumentet til det andrefn (), kalt main (). Vær oppmerksom på at lambda-funksjonen (uttrykket) ikke ender med et semikolon i dette anropet fordi det her er et argument (ikke en frittstående funksjon).

Lambda -funksjonsparameteren i definisjonen av funksjonen otherfn () er en peker til en funksjon. Pekeren har navnet ptr. Navnet, ptr, brukes i definisjonen otherfn () for å kalle lambda -funksjonen.

Uttalelsen,

intnr2= (*ptr)(2);

I den andrefn () definisjonen kaller den lambda -funksjonen med et argument på 2. Returverdien for anropet, '(*ptr) (2)' fra lambda -funksjonen, er tildelt no2.

Programmet ovenfor viser også hvordan lambda -funksjonen kan brukes i C ++ tilbakeringingsfunksjonsskjemaet.

Deler av Lambda Expression

Delene av en typisk lambda -funksjon er som følger:

[] () {}
  • [] er fangstklausulen. Den kan ha varer.
  • () er for parameterlisten.
  • {} er for funksjonskroppen. Hvis funksjonen står alene, bør den ende med et semikolon.

Fanger

Lambda -funksjonsdefinisjonen kan tilordnes en variabel eller brukes som argument til et annet funksjonsanrop. Definisjonen for et slikt funksjonsanrop bør ha som en parameter, en peker til en funksjon, som tilsvarer definisjonen av lambda -funksjonen.

Lambda -funksjonsdefinisjonen er forskjellig fra den normale funksjonsdefinisjonen. Den kan tilordnes en variabel i det globale omfanget; denne funksjonstildelte-til-variabelen kan også kodes i en annen funksjon. Når den er tilordnet en global omfangsvariabel, kan kroppen se andre variabler i det globale omfanget. Når den er tilordnet en variabel i en normal funksjonsdefinisjon, kan kroppen bare se andre variabler i funksjonsomfanget med hjelp av fangstklausulen, [].

Capture-klausulen [], også kjent som lambda-introduktøren, gjør at variabler kan sendes fra det omkringliggende (funksjon) omfanget til lambda-uttrykkets funksjonslegeme. Det sies at lambda -uttrykkets funksjonslegeme fanger variabelen når den mottar objektet. Uten fangstklausulen [] kan en variabel ikke sendes fra det omkringliggende omfanget til lambda -uttrykkets funksjonskropp. Følgende program illustrerer dette, med hovedfunksjonen () som omfanget:

#inkludere

ved hjelp av navneområdetimer;

inthoved-()

{

intid= 5;


autofn= [id]()

{

koste <<id<< ' n';

};

fn();


komme tilbake 0;

}

Utgangen er 5 . Uten navnet, id, inne [], ville lambda -uttrykket ikke ha sett variabelen id for hovedfunksjonen ().

Fange med referanse

Eksemplet ovenfor på bruk av fangstklausulen er å fange etter verdi (se detaljer nedenfor). Ved fangst ved referanse blir plasseringen (lagringen) av variabelen, f.eks. Id ovenfor, av det omkringliggende omfanget tilgjengeliggjort inne i lambda -funksjonskroppen. Så hvis du endrer verdien av variabelen inne i lambda -funksjonskroppen, endres verdien av den samme variabelen i det omkringliggende omfanget. Hver variabel som gjentas i fangstklausulen går foran ampersanden (&) for å oppnå dette. Følgende program illustrerer dette:

#inkludere

ved hjelp av navneområdetimer;

inthoved-()

{

intid= 5; flyteft= 2.3; røyekap= 'TIL';

autofn= [&ID,&fot,&kap]()

{

id= 6;ft= 3.4;kap= 'B';

};

fn();

koste <<id<< ',' <<ft<< ',' <<kap<< ' n';

komme tilbake 0;

}

Utgangen er:

6, 3.4, B

Bekrefter at variabelnavnene inne i lambda -uttrykkets funksjonsdel er for de samme variablene utenfor lambda -uttrykket.

Fange etter verdi

Ved registrering av verdi blir en kopi av variablens plassering, av det omkringliggende omfanget, tilgjengeliggjort inne i lambda -funksjonskroppen. Selv om variabelen inne i lambda -funksjonskroppen er en kopi, kan verdien ikke endres inne i kroppen per nå. For å oppnå fangst etter verdi, går ingen variabel foran hver variabel som gjentas i fangstparagrafen. Følgende program illustrerer dette:

#inkludere

ved hjelp av navneområdetimer;

inthoved-()

{

intid= 5; flyteft= 2.3; røyekap= 'TIL';

autofn= [id, ft, ch]()

{

// id = 6; fot = 3,4; ch = 'B';

koste <<id<< ',' <<ft<< ',' <<kap<< ' n';

};

fn();

id= 6;ft= 3.4;kap= 'B';

koste <<id<< ',' <<ft<< ',' <<kap<< ' n';

komme tilbake 0;

}

Utgangen er:

5, 2.3, A

6, 3.4, B

Hvis kommentarindikatoren fjernes, vil ikke programmet kompilere. Kompilatoren vil gi en feilmelding om at variablene i funksjonsorganets definisjon av lambda -uttrykket ikke kan endres. Selv om variablene ikke kan endres inne i lambda -funksjonen, kan de endres utenfor lambda -funksjonen, som programmet ovenfor viser.

Mixing Captures

Å fange etter referanse og fange etter verdi kan blandes, som følgende program viser:

#inkludere

ved hjelp av navneområdetimer;

inthoved-()

{

intid= 5; flyteft= 2.3; røyekap= 'TIL'; boolbl= ekte;


autofn= [ID, ft,&ch,&bl]()

{

kap= 'B';bl= falsk;

koste <<id<< ',' <<ft<< ',' <<kap<< ',' <<bl<< ' n';

};

fn();


komme tilbake 0;

}

Utgangen er:

5, 2.3, B, 0

Når alle er fanget, er de som referanse:

Hvis alle variablene som skal fanges opp blir fanget opp med referanse, vil bare en & være tilstrekkelig i fangstparagrafen. Følgende program illustrerer dette:

#inkludere

ved hjelp av navneområdetimer;

inthoved-()

{

intid= 5; flyteft= 2.3; røyekap= 'TIL'; boolbl= ekte;


autofn= [&]()

{

id= 6;ft= 3.4;kap= 'B';bl= falsk;

};

fn();

koste <<id<< ',' <<ft<< ',' <<kap<< ',' <<bl<< ' n';


komme tilbake 0;

}

Utgangen er:

6, 3.4, B, 0

Hvis noen variabler skal fanges opp med referanse og andre etter verdi, representerer en & alle referansene, og resten vil ikke gå foran noe som det følgende programmet viser:

ved hjelp av navneområdetimer;

inthoved-()

{

intid= 5; flyteft= 2.3; røyekap= 'TIL'; boolbl= ekte;


autofn= [&, id, ft]()

{

kap= 'B';bl= falsk;

koste <<id<< ',' <<ft<< ',' <<kap<< ',' <<bl<< ' n';

};

fn();


komme tilbake 0;

}

Utgangen er:

5, 2.3, B, 0

Vær oppmerksom på at & alene (dvs. & ikke etterfulgt av en identifikator) må være det første tegnet i fangstparagrafen.

Når alle fanget, er etter verdi:

Hvis alle variablene som skal fanges opp skal fanges opp med verdi, vil bare én = være tilstrekkelig i fangstparagrafen. Følgende program illustrerer dette:

#inkludere

ved hjelp av navneområdetimer;

inthoved-()
{

intid= 5; flyteft= 2.3; røyekap= 'TIL'; boolbl= ekte;


autofn= [=]()

{

koste <<id<< ',' <<ft<< ',' <<kap<< ',' <<bl<< ' n';

};

fn();


komme tilbake 0;


}

Utgangen er:

5, 2.3, A, 1

Merk : = er skrivebeskyttet, per nå.

Hvis noen variabler skal fanges opp med verdi og andre som referanse, representerer en = alle de skrivebeskrevne kopierte variablene, og resten vil ha &, som følgende program viser:

#inkludere

ved hjelp av navneområdetimer;

inthoved-()

{

intid= 5; flyteft= 2.3; røyekap= 'TIL'; boolbl= ekte;


autofn= [=,&ch,&bl]()

{

kap= 'B';bl= falsk;

koste <<id<< ',' <<ft<< ',' <<kap<< ',' <<bl<< ' n';

};

fn();


komme tilbake 0;

}

Utgangen er:

5, 2.3, B, 0

Vær oppmerksom på at = alene må være det første tegnet i fangstparagrafen.

Klassisk tilbakeringingsfunksjon med Lambda -uttrykk

Følgende program viser hvordan et klassisk tilbakeringingsfunksjonsopplegg kan gjøres med lambda -uttrykket:

#inkludere

ved hjelp av navneområdetimer;

røye *produksjon;


autocba= [](røyeute[])

{

produksjon=ute;

};



tomrommainFunc(røyeinput[],tomrom (*til)(røye[]))

{

(*til)(input);

koste<<'for hovedfunksjon'<<' n';

}


tomromfn()

{

koste<<'Nå'<<' n';

}


inthoved-()

{

røyeinput[] = 'for tilbakeringingsfunksjon';

mainFunc(input, cba);

fn();

koste<<produksjon<<' n';



komme tilbake 0;

}

Utgangen er:

for hovedfunksjon



for tilbakeringingsfunksjon

Husk at når en lambdauttrykkdefinisjon er tilordnet en variabel i det globale omfanget, kan dens funksjonsorgan se globale variabler uten å bruke fangstklausulen.

Den bakre-retur-typen

Returtypen for et lambda -uttrykk er automatisk, noe som betyr at kompilatoren bestemmer returtypen fra returuttrykket (hvis det finnes). Hvis programmereren virkelig vil angi returtypen, vil han gjøre det som i følgende program:

#inkludere

ved hjelp av navneområdetimer;

autofn= [](intStoppe) -> int

{

intsvar=Stoppe+ 3;

komme tilbakesvar;

};


inthoved-()

{

autovariab=fn(2);

koste <<variab<< ' n';


komme tilbake 0;

}

Utgangen er 5. Etter parameterlisten skrives piloperatoren. Dette etterfølges av returtypen (int i dette tilfellet).

Lukking

Vurder følgende kodesegment:

strukturCla

{

intid= 5;

røyekap= 'til';

}obj1, obj2;

Her er Cla navnet på struct -klassen. Obj1 og obj2 er to objekter som vil bli instantiert fra struct -klassen. Lambda -uttrykk er lik i implementeringen. Lambda -funksjonsdefinisjonen er en slags klasse. Når lambda -funksjonen kalles (påkalles), blir et objekt øyeblikkelig ut fra definisjonen. Dette objektet kalles en lukning. Det er nedleggelsen som gjør jobben lambda forventes å gjøre.

Imidlertid vil koding av lambda -uttrykket som strukturen ovenfor ha obj1 og obj2 erstattet av de tilsvarende parameternes argumenter. Følgende program illustrerer dette:

#inkludere

ved hjelp av navneområdetimer;

autofn= [](intparam1,intparam2)

{

intsvar=param1+param2;

komme tilbakesvar;

} (2,3);


inthoved-()

{

autohvor=fn;

koste <<hvor<< ' n';


komme tilbake 0;

}

Utgangen er 5. Argumentene er 2 og 3 i parentes. Vær oppmerksom på at lambda uttrykk funksjon kall, fn, ikke tar noen argumenter siden argumentene allerede er blitt kodet på slutten av lambda funksjon definisjon.

Konklusjon

Lambda -uttrykket er en anonym funksjon. Det er i to deler: klasse og objekt. Definisjonen er en slags klasse. Når uttrykket kalles, dannes et objekt ut fra definisjonen. Dette objektet kalles en lukning. Det er nedleggelsen som gjør jobben lambda forventes å gjøre.

For at lambda-uttrykket skal motta en variabel fra et ytre funksjonsomfang, trenger det en ikke-tom fangstklausul i funksjonskroppen.