C ++

Lambda-väljendid C ++ keeles

Lambda-väljendid C ++ keeles

Miks Lambda Expression?

Vaatleme järgmist väidet:

    int myInt = 52;

Siin on myInt identifikaator, väärtus. 52 on sõna otseses mõttes, prvalue. Täna on võimalik funktsioon spetsiaalselt kodeerida ja panna see 52-le. Sellist funktsiooni nimetatakse lambda avaldiseks. Mõelge ka järgmisele lühiprogrammile:

# kaasata
nimeruumi kasutamine std;
int fn (int par)

int vastus = par + 3;
tagasi vastus;

int main ()

fn (5);
tagastama 0;

Täna on võimalik funktsiooni spetsiaalselt kodeerida ja panna funktsiooni kutse fn (5) argumendi positsiooni. Sellist funktsiooni nimetatakse lambda avaldiseks. Selles asendis olev lambda avaldis (funktsioon) on eelväärtus.

Iga literaal, välja arvatud stringi literaal, on prvalue. Lambda avaldis on erifunktsioonide kujundus, mis sobiks koodis sõna otseses mõttes. See on anonüümne (nimetu) funktsioon. Selles artiklis selgitatakse uut C ++ esmast väljendit, mida nimetatakse lambda väljendiks. Selle artikli mõistmiseks on nõutavad algteadmised C ++ keeles.

Artikli sisu

  • Lambda ekspressiooni illustratsioon
  • Lambda väljenduse osad
  • Pildistab
  • Klassikaline tagasihelistamisfunktsioonide skeem koos lambda väljendiga
  • Tagasi-tagasi-tüüp
  • Sulgemine
  • Järeldus

Lambda ekspressiooni illustratsioon

Järgmises programmis määratakse muutujale funktsioon, mis on lambda avaldis:

# kaasata
nimeruumi kasutamine std;
auto fn = [] (int parameeter)

int vastus = param + 3;
tagasi vastus;
;
int main ()

automaatne muutuja = fn (2);
cout << variab << '\n';
tagastama 0;

Väljund on:

    5

Funktsiooni main () kõrval on muutuja fn. Selle tüüp on automaatne. Automaatne tähendab antud olukorras seda, et tegeliku tüübi, näiteks int või float, määrab määramise operaatori õige operand (=). Omistusoperaatori paremal on lambda avaldis. Lambda avaldis on funktsioon ilma eelneva tagasitüübita. Pange tähele nurksulgude kasutamist ja asukohta, []. Funktsioon tagastab 5, int, mis määrab fn tüübi.

Funktsioonis main () on lause:

    automaatne muutuja = fn (2);

See tähendab, et fn väljaspool main () on funktsiooni identifikaator. Selle kaudsed parameetrid on lambda ekspressiooni parameetrid. Muutuja tüüp on auto.

Pange tähele, et lambda avaldis lõpeb semikooloniga, täpselt nagu klass või struktuuri määratlus, lõpeb semikooloniga.

Järgmises programmis on funktsioon, mis on lambda avaldis, mis tagastab väärtuse 5, argumendiks teisele funktsioonile:

# kaasata
nimeruumi kasutamine std;
void otherfn (int no1, int (* ptr) (int))

int nr2 = (* ptr) (2);
cout << no1 << " << no2 << '\n';

int main ()

muufn (4, [] (int param)

int vastus = param + 3;
tagasi vastus;
);
tagastama 0;

Väljund on:

    4 5

Siin on kaks funktsiooni, lambda avaldis ja funktsioon otherfn (). Lambda avaldis on teise argumendi otherfn () nimega main (). Pange tähele, et lambda funktsioon (avaldis) ei lõpe selles kõnes semikooloniga, kuna siin on see argument (mitte eraldiseisev funktsioon).

Funktsiooni parameeter lambda funktsiooni otherfn () määratluses on funktsiooni kursor. Kursoril on nimi, ptr. Nime ptr kasutatakse funktsiooni lambda kutsumiseks definitsioonis otherfn ().

Avaldus,

    int nr2 = (* ptr) (2);

Definitsioonis otherfn () kutsub see lambda funktsiooni argumendiga 2. Kõne tagasiväärtus "(* ptr) (2)" lambda funktsioonist määratakse numbrile2.

Ülalolev programm näitab ka seda, kuidas funktsiooni lambda saab kasutada C ++ tagasihelistamisfunktsioonide skeemis.

Lambda väljenduse osad

Tüüpilise lambda funktsiooni osad on järgmised:

    [] ()
  • [] on püüdmisklausel. Sellel võib olla esemeid.
  • () on parameetrite loendi jaoks.
  • on funktsiooni kehale. Kui funktsioon seisab üksi, peaks see lõppema semikooloniga.

Pildistab

Funktsiooni lambda määratluse saab määrata muutujale või kasutada argumendina teisele funktsioonikutsele. Sellise funktsioonikõne definitsioonil peaks olema parameetrina funktsiooni kursor, mis vastab funktsiooni lambda määratlusele.

Lambda funktsiooni määratlus erineb tavalise funktsiooni määratlusest. Selle saab määrata muutujale globaalses ulatuses; selle muutujale määratud funktsioonile saab kodeerida ka teise funktsiooni. Kui see on määratud globaalse ulatusega muutujale, näeb selle keha teisi globaalse ulatuse muutujaid. Kui see on määratud muutujale normaalse funktsiooni definitsiooni sees, näeb selle keha funktsiooni ulatuses teisi muutujaid ainult püüdmisklausli abiga, [].

Püüdmisklausel [], tuntud ka kui lambda sissejuhataja, võimaldab muutujaid ümbritsevast (funktsiooni) ulatusest saata lambda avaldise funktsiooni kehasse. Väidetavalt tabab lambda avaldise funktsioon keha muutuja objekti vastuvõtmisel. Ilma püüdmisklauslita [] ei saa muutujat ümbritsevast ulatusest saata lambda avaldise funktsiooni kehasse. Järgmine programm illustreerib seda funktsiooni main () funktsiooni ulatusega ümbritseva ulatusena:

# kaasata
nimeruumi kasutamine std;
int main ()

int id = 5;
auto fn = [id] ()

cout << id << '\n';
;
fn ();
tagastama 0;

Väljund on 5. Ilma nime, id, sees [] poleks lambda avaldis näinud funktsiooni main () funktsiooni muutuja id.

Jäädvustamine viite abil

Ülaltoodud näide püüdmisklauslist on väärtuse järgi hõivamine (vt üksikasju allpool). Viite abil hõivamisel muutuja asukoht (salvestusruum), nt.g., Ülal olev ümbritseva ulatusega id on kättesaadav lambda funktsioonikorpuse sees. Niisiis muudab lambda funktsiooni keha muutuja väärtuse muutmine sama muutuja väärtust ümbritsevas ulatuses. Igale püüdmisklauslis korratavale muutujale eelneb selle saavutamiseks tähis (ja). Järgmine programm illustreerib seda:

# kaasata
nimeruumi kasutamine std;
int main ()

int id = 5; ujuk ft = 2.3; char ch = 'A';
auto fn = [& id, & ft, & ch] ()

id = 6; ft = 3.4; ch = 'B';
;
fn ();
cout << id << ", " <<  ft << ", " <<  ch << '\n';
tagastama 0;

Väljund on:

    6, 3.4, B

Kinnitades, et muutuja nimed lambda avaldise funktsiooni kehas on samade muutujate jaoks väljaspool lambda avaldist.

Väärtuse järgi jäädvustamine

Väärtuse järgi hõivamisel tehakse lambda funktsiooni kehas kättesaadavaks koopia muutuja asukohast ja ümbritsevast ulatusest. Kuigi lambda funktsiooni keha muutuja on koopia, ei saa selle väärtust keha sees praegu muuta. Väärtuse järgi hõivamise saavutamiseks ei eelne igale püüdmisklauslis korratud muutujale midagi. Järgmine programm illustreerib seda:

# kaasata
nimeruumi kasutamine std;
int main ()

int id = 5; ujuk ft = 2.3; char ch = 'A';
auto fn = [id, jalad, 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';
tagastama 0;

Väljund on:

5, 2.3, A
6, 3.4, B

Kommentaari indikaatori eemaldamisel programm ei kompileeri. Koostaja väljastab veateate, et funktsiooni keha lambda avaldise definitsioonis olevaid muutujaid ei saa muuta. Kuigi muutujaid ei saa lambda funktsiooni sees muuta, saab neid muuta väljaspool lambda funktsiooni, nagu näitab ülaltoodud programmi väljund.

Salvestuste segamine

Viide ja väärtuse järgi jäädvustamist saab segada, nagu näitab järgmine programm:

# kaasata
nimeruumi kasutamine std;
int main ()

int id = 5; ujuk ft = 2.3; char ch = 'A'; bool bl = tõene;
automaatne fn = [id, ft, & ch, & bl] ()

ch = 'B'; bl = vale;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
tagastama 0;

Väljund on:

    5, 2.3, B, 0

Kui kõik on jäädvustatud, on need viitena:

Kui kõik hõivatavad muutujad on hõivatud viitena, siis piisab haaramisklauslis vaid ühest ja sellest. Järgmine programm illustreerib seda:

# kaasata
nimeruumi kasutamine std;
int main ()

int id = 5; ujuk ft = 2.3; char ch = 'A'; bool bl = tõene;
auto fn = [&] ()

id = 6; ft = 3.4; ch = 'B'; bl = vale;
;
fn ();
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
tagastama 0;

Väljund on:

6, 3.4, B, 0

Kui mõningaid muutujaid tuleb lüüa viitena ja teisi väärtuse järgi, siis üks ja kõik esindavad kõiki viiteid ning ülejäänutele ei eelne midagi, nagu näitab järgmine programm:

nimeruumi kasutamine std;
int main ()

int id = 5; ujuk ft = 2.3; char ch = 'A'; bool bl = tõene;
auto fn = [&, id, jalga] ()

ch = 'B'; bl = vale;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
tagastama 0;

Väljund on:

5, 2.3, B, 0

Pange tähele, et & üksi (st.e., & millele järgneb identifikaator) peab olema püüdmisklausli esimene märk.

Kui kõik on hõivatud, on need väärtuse järgi:

Kui kõik hõivatavad muutujad tuleb hõivata väärtuse järgi, siis piisab püüdmisklauslis vaid ühest =. Järgmine programm illustreerib seda:

# kaasata
nimeruumi kasutamine std;
int main ()

int id = 5; ujuk ft = 2.3; char ch = 'A'; bool bl = tõene;
automaatne fn = [=] ()

cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
tagastama 0;

Väljund on:

5, 2.3, A, 1

Märge: = on praegu kirjutuskaitstud.

Kui mõned muutujad tuleb püüda väärtuse ja teised viitega, siis üks = tähistab kõiki kirjutuskaitstud kopeeritud muutujaid ja ülejäänud on mõlemal &, nagu näitab järgmine programm:

# kaasata
nimeruumi kasutamine std;
int main ()

int id = 5; ujuk ft = 2.3; char ch = 'A'; bool bl = tõene;
auto fn = [=, & ch, & bl] ()

ch = 'B'; bl = vale;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
tagastama 0;

Väljund on:

5, 2.3, B, 0

Pange tähele, et = üksi peab olema püüdmisklausli esimene märk.

Klassikaline tagasihelistamisfunktsioonide skeem koos lambda väljendiga

Järgmine programm näitab, kuidas klassikalist tagasihelistamisfunktsiooni skeemi saab teha lambda avaldisega:

# kaasata
nimeruumi kasutamine std;
char * väljund;
automaatne cba = [] (char out [])

väljund = välja;
;
void basicFunc (char sisend [], void (* pt) (char []))

(* pt) (sisend);
cout<<"for principal function"<<'\n';

tühine fn ()

cout<<"Now"<<'\n';

int main ()

char input [] = "tagasihelistamisfunktsiooni jaoks";
peamineFunk (sisend, cba);
fn ();
cout<tagastama 0;

Väljund on:

põhifunktsiooniks
Nüüd
tagasihelistamisfunktsiooni jaoks

Tuletame meelde, et kui lambda-väljendi määratlus määratakse muutujale globaalses ulatuses, saab selle funktsioonikeha näha globaalseid muutujaid püüdmislauset kasutamata.

Tagasi-tagasi-tüüp

Lambda avaldise tagastustüüp on auto, mis tähendab, et kompilaator määrab tagasituleku tüübi tagastava avaldise järgi (kui see on olemas). Kui programmeerija soovib tõesti märkida tagastuse tüübi, teeb ta seda nii nagu järgmises programmis:

# kaasata
nimeruumi kasutamine std;
auto fn = [] (int param) -> int

int vastus = param + 3;
tagasi vastus;
;
int main ()

automaatne muutuja = fn (2);
cout << variab << '\n';
tagastama 0;

Väljund on 5. Pärast parameetrite loendit sisestatakse nooleoperaator. Sellele järgneb tagastuse tüüp (antud juhul int).

Sulgemine

Mõelge järgmisele koodisegmendile:

struct Cla

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

Siin on Cla struktuuri klassi nimi.  Obj1 ja obj2 on kaks objekti, mis instantsitakse struktuuri klassist. Lambda väljend on rakendamisel sarnane. Lambda funktsiooni määratlus on omamoodi klass. Kui lambda-funktsiooni kutsutakse (kutsutakse), siis objekt on selle definitsioonist lähtuv. Seda objekti nimetatakse sulgemiseks. See on sulgemine, mis teeb lambda eeldatava töö.

Kuid lambda avaldise kodeerimisel nagu ülaltoodud struktuuris, asendatakse obj1 ja obj2 vastavate parameetrite argumentidega. Järgmine programm illustreerib seda:

# kaasata
nimeruumi kasutamine std;
auto fn = [] (int param1, int param2)

int vastus = param1 + param2;
tagasi vastus;
(2, 3);
int main ()

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

Väljund on 5. Argumendid on sulgudes 2 ja 3. Pange tähele, et lambda avaldise funktsioonikõne fn ei võta ühtegi argumenti, kuna argumendid on juba lambda funktsiooni definitsiooni lõpus.

Järeldus

Lambda väljend on anonüümne funktsioon. See on kahes osas: klass ja objekt. Selle määratlus on omamoodi klass. Kui väljendit kutsutakse, moodustatakse määratlusest objekt. Seda objekti nimetatakse sulgemiseks. See on sulgemine, mis teeb lambda eeldatava töö.

Selleks, et lambda avaldis saaks muutuja väljastpoolt funktsiooni ulatust, vajab see oma funktsiooni kehasse tühja püüdmisklauslit.

Tomb Raider for Linuxi õpetus
Shadow of the Tomb Raider on kaheteistkümnes täiendus seeria Tomb Raider - tegevus- ja seiklusmängude frantsiisile, mille on loonud Eidos Montreal. Ni...
Kuidas FPS-i suurendada Linuxis?
FPS tähistab Kaadrit sekundis. FPS-i ülesanne on mõõta kaadrisagedust video taasesitamisel või mängude esitamisel. Lihtsamalt öeldes nimetatakse iga s...
Parimad Oculus App Lab mängud
Kui olete Oculuse peakomplekti omanik, peate olema teadlik külglaadimisest. Kõrvalaadimine on protsess, millega installitakse peakomplekti mitte-poesi...