C ++

Lambda izrazi u C ++

Lambda izrazi u C ++

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:

#include
pomoć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:

#include
pomoć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:

    5

Izvan 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:

#include
pomoć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 5

Ovdje 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:

#include
pomoć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:

#include
pomoć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, B

Potvrđ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:

#include
pomoć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, A
6, 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:

#include
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, & bl] ()

ch = 'B'; bl = lažno;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
return 0;

Izlaz je:

    5, 2.3, B, 0

Kada 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:

#include
pomoć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, 0

Ako ć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, 0

Imajte 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:

#include
pomoć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, 1

Bilješ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:

#include
pomoć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, 0

Imajte 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:

#include
pomoć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<return 0;

Izlaz je:

za glavnu funkciju
Sada
za funkciju povratnog poziva

Sjetimo se da kada je definicija lambda izraza dodijeljena varijabli u globalnom opsegu, njezino tijelo funkcije može vidjeti globalne varijable bez upotrebe klauzule capture.

Tip pratećeg povratka

Tip povratka lambda izraza je automatski, što znači da sastavljač određuje tip povratka iz izraza return (ako je prisutan). Ako programer stvarno želi naznačiti vrstu povrata, učinit će to kao u sljedećem programu:

#include
pomoću prostora imena std;
auto fn = [] (int param) -> int

int odgovor = param + 3;
odgovor na povratak;
;
int main ()

automatski varijab = fn (2);
cout << variab << '\n';
return 0;

Izlaz je 5. Nakon popisa parametara upisuje se operator strelice. Nakon toga slijedi tip povratka (u ovom slučaju int).

Zatvaranje

Razmotrite sljedeći segment koda:

strukturna Cla

int id = 5;
char ch = 'a';
obj1, obj2;

Ovdje je Cla naziv klase struct.  Obj1 i obj2 su dva objekta koja će se izraditi iz klase struct. Lambda izraz je sličan u provedbi. Definicija lambda funkcije svojevrsna je klasa. Kada se lambda funkcija poziva (poziva), objekt se instancira iz njegove definicije. Taj se objekt naziva zatvaranje. Zatvaranje čini ono što se očekuje od lambde.

Međutim, kodiranje lambda izraza poput gornje strukture imat će obj1 i obj2 zamijenjene argumentima odgovarajućih parametara. Sljedeći program to ilustrira:

#include
pomoću prostora imena std;
auto fn = [] (int param1, int param2)

int odgovor = param1 + param2;
odgovor na povratak;
(2, 3);
int main ()

auto var = fn;
cout << var << '\n';
return 0;

Izlaz je 5. Argumenti su 2 i 3 u zagradama. Imajte na umu da poziv funkcije lambda izraza, fn, ne uzima nijedan argument jer su argumenti već kodirani na kraju definicije lambda funkcije.

Zaključak

Lambda izraz je anonimna funkcija. To je iz dva dijela: klase i objekta. Njegova je definicija svojevrsna klasa. Kada se izraz pozove, objekt se oblikuje iz definicije. Taj se objekt naziva zatvaranje. Zatvaranje je ono što obavlja posao koji se očekuje od lambde.

Da bi lambda izraz primio varijablu iz vanjskog opsega funkcije, potrebna je neprazna klauzula za hvatanje u svoje tijelo funkcije.

Kako instalirati League Of Legends na Ubuntu 14.04
Ako ste ljubitelj League of Legends, ovo je prilika za vas da testirate League of Legends. Imajte na umu da je LOL podržan na PlayOnLinux ako ste kori...
Instalirajte najnoviju strategiju igre OpenRA na Ubuntu Linux
OpenRA je Libre / Free Real Time strateški pokretač igre koji stvara rane Westwoodove igre poput klasične Command & Conquer: Red Alert. Distribuirani ...
Instalirajte najnoviji Dolphin Emulator za Gamecube i Wii na Linux
Dolphin Emulator omogućuje vam igranje odabranih Gamecube i Wii igara na Linux osobnim računalima (PC). Dolphin Emulator je slobodno dostupan i emula...