Zakaj Lambda Expression?
Upoštevajte naslednjo izjavo:
int myInt = 52;Tu je myInt identifikator, vrednost. 52 je dobesedno, prva vrednost. Danes je mogoče funkcijo posebej kodirati in jo postaviti v položaj 52. Takšni funkciji pravimo lambda izraz. Upoštevajte tudi naslednji kratek program:
#includeuporaba imenskega prostora std;
int fn (int par)
int odgovor = par + 3;
povratni odgovor;
int main ()
fn (5);
vrnitev 0;
Danes je mogoče funkcijo posebej kodirati in jo postaviti v položaj argumenta 5, klica funkcije, fn (5). Takšni funkciji pravimo lambda izraz. Lambda izraz (funkcija) v tem položaju je prva vrednost.
Katera koli dobesedna črka, razen nizovne, je prva vrednost. Lambda izraz je posebna zasnova funkcije, ki bi se v kodi prilegala kot dobesedno besedilo. Gre za anonimno (neimenovano) funkcijo. Ta članek pojasnjuje novi primarni izraz C ++, imenovan lambda izraz. Osnovno znanje jezika C ++ je pogoj za razumevanje tega članka.
Vsebina članka
- Prikaz Lambda izražanja
- Deli Lambda Expression
- Zajemanje
- Klasična shema funkcije povratnega klica z Lambda Expression
- Vrsta zaključnega vrnitve
- Zaključek
- Zaključek
Prikaz Lambda izražanja
V naslednjem programu je spremenljivki dodeljena funkcija, ki je lambda izraz:
#includeuporaba imenskega prostora std;
samodejno fn = [] (int param)
int odgovor = param + 3;
povratni odgovor;
;
int main ()
samodejna spremenljivka = fn (2);
cout << variab << '\n';
vrnitev 0;
Rezultat je:
5Zunaj glavne () funkcije je spremenljivka fn. Njegova vrsta je samodejna. Samodejno v tej situaciji pomeni, da dejanski tip, na primer int ali float, določa desni operand operaterja dodelitve (=). Na desni strani operaterja dodelitve je lambda izraz. Lambda izraz je funkcija brez predhodnega tipa vrnitve. Upoštevajte uporabo in položaj oglatih oklepajev, []. Funkcija vrne 5, int, ki bo določil vrsto za fn.
V glavni () funkciji je stavek:
samodejna spremenljivka = fn (2);To pomeni, da se fn zunaj main () konča kot identifikator funkcije. Njeni implicitni parametri so parametri lambda izraza. Tip za variab je samodejno.
Upoštevajte, da se lambda izraz konča s podpičjem, tako kot definicija razreda ali strukture, s podpičjem.
V naslednjem programu je funkcija, ki je lambda izraz, ki vrne vrednost 5, argument drugi funkciji:
#includeuporaba imenskega prostora std;
void otherfn (int št1, int (* ptr) (int))
int št2 = (* ptr) (2);
cout << no1 << " << no2 << '\n';
int main ()
otherfn (4, [] (int param)
int odgovor = param + 3;
povratni odgovor;
);
vrnitev 0;
Rezultat je:
4 5Tu sta dve funkciji, lambda izraz in funkcija otherfn (). Lambda izraz je drugi argument drugefn (), ki se imenuje main (). Upoštevajte, da se lambda funkcija (izraz) v tem klicu ne konča s podpičjem, ker je tu argument (ne samostojna funkcija).
Parameter lambda funkcije v definiciji funkcije otherfn () je kazalec na funkcijo. Kazalec ima ime, ptr. Ime, ptr, se uporablja v definiciji otherfn () za klicanje funkcije lambda.
Izjava,
int št2 = (* ptr) (2);V definiciji otherfn () prikliče funkcijo lambda z argumentom 2. Vrnjena vrednost klica, "(* ptr) (2)" iz funkcije lambda, je dodeljena no2.
Zgornji program prikazuje tudi, kako lahko funkcijo lambda uporabljamo v shemi funkcij povratnega klica C ++.
Deli Lambda Expression
Deli tipične lambda funkcije so naslednji:
[] ()- [] je klavzula za zajem. Lahko ima predmete.
- () je za seznam parametrov.
- je za telo funkcije. Če funkcija stoji samostojno, se mora končati s podpičjem.
Zajemanje
Definicijo lambda funkcije lahko dodelite spremenljivki ali uporabite kot argument za drug klic funkcije. Definicija za tak klic funkcije mora imeti kot parameter kazalec na funkcijo, ki ustreza definiciji lambda funkcije.
Definicija lambda funkcije se razlikuje od običajne definicije funkcije. Lahko se dodeli spremenljivki v globalnem obsegu; ta funkcija, dodeljena spremenljivki, se lahko kodira tudi znotraj druge funkcije. Ko je telo dodeljeno spremenljivki globalnega obsega, lahko vidi druge spremenljivke v globalnem obsegu. Ko je telo dodeljeno spremenljivki znotraj običajne definicije funkcije, lahko vidi druge spremenljivke v obsegu funkcije samo s pomočjo klavzule za zajem, [].
Klavzula za zajemanje [], znana tudi kot lambda-uvodnik, omogoča pošiljanje spremenljivk iz okolice (funkcije) v telo funkcije lambda izraza. Telo funkcije lambda izraza naj bi zajemalo spremenljivko, ko prejme objekt. Brez klavzule zajemanja [] spremenljivke ni mogoče poslati iz okoliškega obsega v telo funkcije lambda izraza. Naslednji program to ponazarja z obsegom funkcije main () kot okoliškim obsegom:
#includeuporaba imenskega prostora std;
int main ()
int id = 5;
samodejno fn = [id] ()
cout << id << '\n';
;
fn ();
vrnitev 0;
Izhod je 5. Brez imena, id znotraj [] lambda izraz ne bi videl spremenljivke id področja funkcije main ().
Zajem z referenco
Zgornji primer uporabe stavka zajemanje je zajem po vrednosti (glej podrobnosti spodaj). Pri zajemanju s sklicem je lokacija (shranjevanje) spremenljivke, npr.g., ID zgoraj, okoliškega obsega, je na voljo znotraj telesa lambda funkcije. Torej, sprememba vrednosti spremenljivke v telesu funkcije lambda bo spremenila vrednost iste spremenljivke v okoliškem obsegu. Za dosego tega pred vsako spremenljivko, ki se ponovi v stavku zajemanja, stoji znak & (&). Naslednji program to ponazarja:
#includeuporaba imenskega prostora std;
int main ()
int id = 5; float ft = 2.3; char ch = 'A';
samodejno fn = [& id, & ft, & ch] ()
id = 6; ft = 3.4; ch = 'B';
;
fn ();
cout << id << ", " << ft << ", " << ch << '\n';
vrnitev 0;
Rezultat je:
6, 3.4, BPotrditev, da so imena spremenljivk znotraj telesa funkcije lambda izraza enaka spremenljivkam zunaj lambda izraza.
Zajemanje po vrednosti
Pri zajemanju po vrednosti je v telesu funkcije lambda na voljo kopija lokacije spremenljivke in okoliškega obsega. Čeprav je spremenljivka v telesu lambda funkcije kopija, njene vrednosti od zdaj ni mogoče spremeniti znotraj telesa. Da bi dosegli zajem po vrednosti, pred vsako spremenljivko, ponovljeno v stavku zajemanja, ne stoji nič. Naslednji program to ponazarja:
#includeuporaba imenskega prostora std;
int main ()
int id = 5; float ft = 2.3; char ch = 'A';
samodejno 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';
vrnitev 0;
Rezultat je:
5, 2.3, A6, 3.4, B
Če indikator komentarja odstranite, se program ne bo prevedel. Prevajalnik bo izdal sporočilo o napaki, da spremenljivk v definiciji lambda izraza v funkcijskem telesu ni mogoče spremeniti. Čeprav spremenljivk ni mogoče spremeniti znotraj lambda funkcije, jih je mogoče spremeniti zunaj lambda funkcije, kot kaže zgornji izhod programa.
Mešanje posnetkov
Zajem z referenco in zajem z vrednostjo je mogoče mešati, kot kaže naslednji program:
#includeuporaba imenskega prostora std;
int main ()
int id = 5; float ft = 2.3; char ch = 'A'; bool bl = res;
samodejno fn = [id, ft, & ch, & bl] ()
ch = 'B'; bl = napačno;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
vrnitev 0;
Rezultat je:
5, 2.3, B, 0Ko so vsi zajeti, so po sklicu:
Če so vse spremenljivke, ki jih je treba zajeti, zajete s sklicem, bo v stavku za zajemanje zadostovala samo ena &. Naslednji program to ponazarja:
#includeuporaba imenskega prostora std;
int main ()
int id = 5; float ft = 2.3; char ch = 'A'; bool bl = res;
samodejno fn = [&] ()
id = 6; ft = 3.4; ch = 'B'; bl = napačno;
;
fn ();
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
vrnitev 0;
Rezultat je:
6, 3.4, B, 0Če je treba nekatere spremenljivke zajeti s sklicem, druge pa z vrednostjo, potem bo ena & predstavljala vse sklice, pred ostalimi pa ne bo nič, kot kaže naslednji program:
uporaba imenskega prostora std;int main ()
int id = 5; float ft = 2.3; char ch = 'A'; bool bl = res;
samodejno fn = [&, id, ft] ()
ch = 'B'; bl = napačno;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
vrnitev 0;
Rezultat je:
5, 2.3, B, 0Upoštevajte, da & sam (i.e., & ne sledi mu identifikator) mora biti prvi znak v stavku za zajemanje.
Ko so vsi zajeti, so po vrednosti:
Če je treba vse spremenljivke, ki jih je treba zajeti, zajeti po vrednosti, potem bo v klavzuli za zajemanje zadostovalo samo eno =. Naslednji program to ponazarja:
#includeuporaba imenskega prostora std;
int main ()
int id = 5; float ft = 2.3; char ch = 'A'; bool bl = res;
samodejno fn = [=] ()
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
vrnitev 0;
Rezultat je:
5, 2.3, A, 1Opomba: = je od zdaj samo za branje.
Če je treba nekatere spremenljivke zajeti z vrednostjo, druge pa s sklicem, potem bo ena = predstavljala vse samo za branje kopirane spremenljivke, ostale pa bodo imele &, kot kaže naslednji program:
#includeuporaba imenskega prostora std;
int main ()
int id = 5; float ft = 2.3; char ch = 'A'; bool bl = res;
samodejno fn = [=, & ch, & bl] ()
ch = 'B'; bl = napačno;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
vrnitev 0;
Rezultat je:
5, 2.3, B, 0Upoštevajte, da mora biti = same prvi znak v stavku za zajem.
Klasična shema funkcije povratnega klica z Lambda Expression
Naslednji program prikazuje, kako lahko izvedemo klasično shemo funkcij povratnega klica z lambda izrazom:
#includeuporaba imenskega prostora std;
char * izhod;
samodejno cba = [] (črka ven [])
izhod = ven;
;
void principalFunc (vnos znaka [], void (* pt) (char []))
(* pt) (vnos);
cout<<"for principal function"<<'\n';
void fn ()
cout<<"Now"<<'\n';
int main ()
char input [] = "za funkcijo povratnega klica";
principalFunc (vnos, cba);
fn ();
cout<