Zašto Lambda Expression?
Razmotrite sljedeću izjavu:
int myInt = 52;Ovdje je myInt identifikator, vrijednost. 52 je doslovno, prva vrijednost. Danas je moguće posebno kodirati funkciju i staviti je u položaj 52. Takva se funkcija naziva lambda izraz. Uzmite u obzir i sljedeći kratki program:
#includepomoću prostora imena std;
int fn (int par)
int odgovor = par + 3;
odgovor na povratak;
int main ()
fn (5);
return 0;
Danas je moguće posebno kodirati funkciju i staviti je u položaj argumenta 5, poziva funkcije, fn (5). Takva se funkcija naziva lambda izraz. Lambda izraz (funkcija) u tom položaju prva je vrijednost.
Bilo koja literala, osim doslovne, je prva vrijednost. Lambda izraz je poseban dizajn funkcije koji bi odgovarao kao doslovnom kodu. To je anonimna (neimenovana) funkcija. Ovaj članak objašnjava novi primarni izraz C ++, nazvan lambda izraz. Osnovno znanje na C ++-u uvjet je za razumijevanje ovog članka.
Sadržaj članka
- Ilustracija Lambda izraza
- Dijelovi Lambda izraza
- Hvatanja
- Klasična shema funkcije povratnog poziva s Lambda izrazom
- Tip pratećeg povratka
- Zatvaranje
- Zaključak
Ilustracija Lambda izraza
U sljedećem programu, varijabli je dodijeljena funkcija koja je lambda izraz:
#includepomoću prostora imena std;
automatski fn = [] (int param)
int odgovor = param + 3;
odgovor na povratak;
;
int main ()
automatski varijab = fn (2);
cout << variab << '\n';
return 0;
Izlaz je:
5Izvan glavne () funkcije nalazi se varijabla fn. Njegova je vrsta auto. Automatski u ovoj situaciji znači da je stvarni tip, poput int ili float, određen desnim operandom operatora dodjele (=). S desne strane operatora dodjele nalazi se lambda izraz. Lambda izraz je funkcija bez prethodnog tipa povratka. Obratite pažnju na upotrebu i položaj uglatih zagrada, []. Funkcija vraća 5, int, koji će odrediti vrstu za fn.
U funkciji main () nalazi se izjava:
automatski varijab = fn (2);To znači da fn izvan main () završava kao identifikator funkcije. Njegovi implicitni parametri su parametri lambda izraza. Tip za varijab je automatski.
Imajte na umu da se lambda izraz završava zarezom, baš kao što definicija klase ili strukture završava zarezom.
U sljedećem programu, funkcija, koja je lambda izraz koji vraća vrijednost 5, argument je drugoj funkciji:
#includepomoću prostora imena std;
void otherfn (int br1, int (* ptr) (int))
int br2 = (* ptr) (2);
cout << no1 << " << no2 << '\n';
int main ()
otherfn (4, [] (int param)
int odgovor = param + 3;
odgovor na povratak;
);
return 0;
Izlaz je:
4 5Ovdje postoje dvije funkcije, lambda izraz i funkcija otherfn (). Lambda izraz je drugi argument otherfn (), pozvan u main (). Imajte na umu da se lambda funkcija (izraz) u ovom pozivu ne završava zarezom jer je ovdje argument (a ne samostalna funkcija).
Parametar lambda funkcije u definiciji funkcije otherfn () pokazivač je na funkciju. Pokazivač ima ime, ptr. Ime, ptr, koristi se u definiciji otherfn () za pozivanje lambda funkcije.
Izjava,
int br2 = (* ptr) (2);U definiciji otherfn () poziva lambda funkciju s argumentom 2. Povratna vrijednost poziva, "(* ptr) (2)" iz lambda funkcije, dodjeljuje se no2.
Gornji program također pokazuje kako se lambda funkcija može koristiti u shemi funkcija povratnog poziva C ++.
Dijelovi Lambda izraza
Dijelovi tipične lambda funkcije su sljedeći:
[] ()- [] je klauzula za hvatanje. Može imati predmete.
- () je za popis parametara.
- je za tijelo funkcije. Ako funkcija stoji samostalno, tada bi trebala završiti točkom i zarezom.
Hvatanja
Definicija lambda funkcije može se dodijeliti varijabli ili koristiti kao argument drugom pozivu funkcije. Definicija takvog poziva funkcije trebala bi kao parametar imati pokazivač na funkciju, koja odgovara definiciji lambda funkcije.
Definicija lambda funkcije razlikuje se od normalne definicije funkcije. Može se dodijeliti varijabli u globalnom opsegu; ova funkcija-dodijeljena-varijabli također se može kodirati unutar druge funkcije. Kad je dodijeljeno globalnoj varijabli opsega, njezino tijelo može vidjeti druge varijable u globalnom opsegu. Kad je dodijeljeno varijabli unutar normalne definicije funkcije, njezino tijelo može vidjeti druge varijable u opsegu funkcije samo uz pomoć klauzule za hvatanje, [].
Klauzula za hvatanje [], također poznata i kao lambda-uvodnik, omogućuje slanje varijabli iz okolnog opsega (funkcije) u tijelo funkcije lambda izraza. Kaže se da tijelo funkcije lambda izraza bilježi varijablu kad primi objekt. Bez klauzule capture [], varijabla se ne može poslati iz okolnog opsega u tijelo funkcije lambda izraza. Sljedeći program to ilustrira s opsegom funkcije main () kao okolnim opsegom:
#includepomoću prostora imena std;
int main ()
int id = 5;
automatski fn = [id] ()
cout << id << '\n';
;
fn ();
return 0;
Izlaz je 5. Bez imena, id, unutar [], lambda izraz ne bi vidio varijablu id opsega funkcije main ().
Snimanje pomoću reference
Gornji primjer upotrebe klauzule capture obuhvaća vrijednost (pogledajte detalje u nastavku). U hvatanju putem reference, mjesto (pohrana) varijable, npr.g., Id gore, okolnog opsega, dostupan je unutar tijela lambda funkcije. Dakle, promjena vrijednosti varijable unutar tijela lambda funkcije promijenit će vrijednost te iste varijable u okolnom opsegu. Svakoj varijabli koja se ponavlja u klauzuli za hvatanje prethodi znak & (&) da bi se to postiglo. Sljedeći program to ilustrira:
#includepomoću prostora imena std;
int main ()
int id = 5; plutati ft = 2.3; char ch = 'A';
automatski fn = [& id, & ft, & ch] ()
id = 6; ft = 3.4; ch = 'B';
;
fn ();
cout << id << ", " << ft << ", " << ch << '\n';
return 0;
Izlaz je:
6, 3.4, BPotvrđujući da su imena varijabli unutar tijela funkcije lambda izraza za iste varijable izvan lambda izraza.
Hvatanje po vrijednosti
Pri hvatanju po vrijednosti, kopija lokacije varijable, okolnog opsega, dostupna je unutar tijela lambda funkcije. Iako je varijabla unutar tijela lambda funkcije kopija, njezina se vrijednost od sada ne može mijenjati unutar tijela. Da bi se postiglo hvatanje po vrijednosti, svakoj varijabli koja se ponavlja u klauzuli za hvatanje ne prethodi ništa. Sljedeći program to ilustrira:
#includepomoću prostora imena std;
int main ()
int id = 5; plutati ft = 2.3; char ch = 'A';
automatski 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';
return 0;
Izlaz je:
5, 2.3, A6, 3.4, B
Ako se ukloni indikator komentara, program se neće sastaviti. Kompajler će izdati poruku o pogrešci da se varijable unutar definicije tijela funkcije funkcije lambda izraza ne mogu mijenjati. Iako se varijable ne mogu mijenjati unutar lambda funkcije, one se mogu mijenjati izvan lambda funkcije, kao što pokazuje gornji izlaz programa.
Miješanje hvatanja
Snimanje pomoću reference i hvatanje po vrijednosti može se kombinirati, kao što pokazuje sljedeći program:
#includepomoću prostora imena std;
int main ()
int id = 5; plutati ft = 2.3; char ch = 'A'; bool bl = točno;
automatski fn = [id, ft, & ch, & bl] ()
ch = 'B'; bl = lažno;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
return 0;
Izlaz je:
5, 2.3, B, 0Kada su svi zarobljeni, referencom su:
Ako su sve varijable koje treba uhvatiti uhvaćene referencom, tada će u klauzuli za hvatanje biti dovoljna samo jedna &. Sljedeći program to ilustrira:
#includepomoću prostora imena std;
int main ()
int id = 5; plutati ft = 2.3; char ch = 'A'; bool bl = točno;
automatski fn = [&] ()
id = 6; ft = 3.4; ch = 'B'; bl = lažno;
;
fn ();
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
return 0;
Izlaz je:
6, 3.4, B, 0Ako će neke varijable biti zabilježene referencom, a druge vrijednošću, tada će jedna & predstavljati sve reference, a ostalima neće ništa prethoditi, kao što pokazuje sljedeći program:
pomoću prostora imena std;int main ()
int id = 5; plutati ft = 2.3; char ch = 'A'; bool bl = točno;
automatski fn = [&, id, ft] ()
ch = 'B'; bl = lažno;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
return 0;
Izlaz je:
5, 2.3, B, 0Imajte na umu da & sam (tj.e., & ne slijedi ga identifikator) mora biti prvi znak u klauzuli snimanja.
Kad su sve zarobljene, imaju vrijednost:
Ako se sve varijable koje treba uhvatiti trebaju zabilježiti po vrijednosti, tada će u klauzuli za hvatanje biti dovoljan samo jedan =. Sljedeći program to ilustrira:
#includepomoću prostora imena std;
int main ()
int id = 5; plutati ft = 2.3; char ch = 'A'; bool bl = točno;
automatski fn = [=] ()
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
return 0;
Izlaz je:
5, 2.3, A, 1Bilješka: = od sada je samo za čitanje.
Ako će neke varijable biti zabilježene vrijednošću, a druge referencom, tada će jedna = predstavljati sve kopirane varijable samo za čitanje, a ostale će imati &, kao što pokazuje sljedeći program:
#includepomoću prostora imena std;
int main ()
int id = 5; plutati ft = 2.3; char ch = 'A'; bool bl = točno;
automatski fn = [=, & ch, & bl] ()
ch = 'B'; bl = lažno;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
return 0;
Izlaz je:
5, 2.3, B, 0Imajte na umu da = alone mora biti prvi znak u klauzuli snimanja.
Klasična shema funkcije povratnog poziva s Lambda izrazom
Sljedeći program pokazuje kako se klasična shema funkcije povratnog poziva može izvesti s lambda izrazom:
#includepomoću prostora imena std;
char * izlaz;
automatski cba = [] (iscrtavanje [])
izlaz = izlaz;
;
void principalFunc (unos znakova [], void (* pt) (char []))
(* pt) (ulaz);
cout<<"for principal function"<<'\n';
void fn ()
cout<<"Now"<<'\n';
int main ()
char input [] = "za funkciju povratnog poziva";
principalFunc (ulaz, cba);
fn ();
cout<