Lambda výrazy v C ++

Lambda Expressions C



Prečo lambda výraz?

Zvážte nasledujúce tvrdenie:

intmyInt= 52;

Tu je myInt identifikátor, hodnota l. 52 je doslovný preklad, prvou hodnotou. Dnes je možné funkciu špeciálne kódovať a postaviť na pozíciu 52. Takáto funkcia sa nazýva výraz lambda. Zvážte tiež nasledujúci krátky program:







#zahrnúť

použitím priestor mienhodiny;

intfn(intcez)

{

intodpovedz=cez+ 3;

vrátiť saodpovedz;

}


intHlavná()

{

fn(5);



vrátiť sa 0;

}

Dnes je možné funkciu špeciálne kódovať a postaviť ju na pozíciu argumentu 5, volania funkcie, fn (5). Takáto funkcia sa nazýva lambda výraz. Výraz (funkcia) lambda v tejto polohe je prvou hodnotou.



Akýkoľvek literál okrem reťazcového literálu je prvou hodnotou. Výraz lambda je návrh špeciálnej funkcie, ktorý by sa v kóde hodil doslovne. Ide o anonymnú (nemenovanú) funkciu. Tento článok vysvetľuje nový primárny výraz C ++, nazývaný výraz lambda. Základné znalosti tohto jazyka sú základné znalosti jazyka C ++.



Obsah článku

Ilustrácia lambda výrazu

V nasledujúcom programe je funkcii, ktorá je výrazom lambda, priradená premenná:





#zahrnúť

použitím priestor mienhodiny;

autofn= [](intzastaviť sa)

{

intodpovedz=zastaviť sa+ 3;

vrátiť saodpovedz;

};


intHlavná()

{

autovariab=fn(2);

náklady <<variab<< ' n';


vrátiť sa 0;

}

Výstupom je:

5

Mimo funkcie main () sa nachádza premenná fn. Jeho typ je automatický. Auto v tejto situácii znamená, že skutočný typ, napríklad int alebo float, je určený pravým operandom operátora priradenia (=). Vpravo od operátora priradenia je výraz lambda. Výraz lambda je funkcia bez predchádzajúceho návratového typu. Všimnite si použitia a umiestnenia hranatých zátvoriek, []. Funkcia vráti hodnotu 5, int, ktorá určí typ pre fn.



Vo funkcii main () je príkaz:

autovariab=fn(2);

To znamená, že fn mimo main () končí ako identifikátor funkcie. Jeho implicitné parametre sú parametre lambda výrazu. Typ pre premennú je automatický.

Všimnite si toho, že výraz lambda končí bodkočiarkou, rovnako ako definícia triedy alebo štruktúry končí bodkočiarkou.

V nasledujúcom programe je funkcia, ktorá je výrazom lambda vracajúcou hodnotu 5, argumentom pre inú funkciu:

#zahrnúť

použitím priestor mienhodiny;

prázdnyotherfn(intč. 1,int (*ptr)(int))

{

intč.2= (*ptr)(2);

náklady <<č. 1<< '' <<č.2<< ' n';

}


intHlavná()

{

otherfn(4,[](intzastaviť sa)

{

intodpovedz=zastaviť sa+ 3;

vrátiť saodpovedz;

});


vrátiť sa 0;
}

Výstupom je:

Štyria, piati

Existujú tu dve funkcie, výraz lambda a funkcia otherfn (). Výraz lambda je druhým argumentom príkazu otherfn (), ktorý sa volá main (). Všimnite si toho, že funkcia lambda (výraz) nekončí v tomto volaní bodkočiarkou, pretože tu ide o argument (nie o samostatnú funkciu).

Parameter funkcie lambda v definícii funkcie otherfn () je ukazovateľom na funkciu. Ukazovateľ má názov ptr. Názov ptr sa používa v definícii otherfn () na volanie funkcie lambda.

Výkaz,

intč.2= (*ptr)(2);

V definícii otherfn () volá funkciu lambda s argumentom 2. Návratová hodnota volania „(*ptr) (2)“ z funkcie lambda je priradená k č. 2.

Vyššie uvedený program tiež ukazuje, ako je možné funkciu lambda použiť v schéme funkcie spätného volania C ++.

Časti lambda výrazu

Časti typickej lambda funkcie sú nasledujúce:

[] () {}
  • [] je doložka o zachytení. Môže obsahovať položky.
  • () je pre zoznam parametrov.
  • {} je pre telo funkcie. Ak je funkcia samostatná, mala by byť ukončená bodkočiarkou.

Zachytáva

Definíciu funkcie lambda je možné priradiť k premennej alebo použiť ako argument pre iné volanie funkcie. Definícia takéhoto volania funkcie by mala mať ako parameter ukazovateľ na funkciu zodpovedajúcu definícii funkcie lambda.

Definícia funkcie lambda sa líši od definície normálnej funkcie. Je možné ho priradiť k premennej v globálnom rozsahu; táto funkcia priradená k premennej môže byť kódovaná aj v rámci inej funkcie. Keď je priradený k premennej globálneho rozsahu, jeho telo môže vidieť ďalšie premenné v globálnom rozsahu. Keď je priradený k premennej v rámci definície normálnej funkcie, jej telo môže vidieť ďalšie premenné v rozsahu funkcie iba s pomocou doložky o zachytení, [].

Zachytávacia doložka [], známa tiež ako zavádzač lambda, umožňuje odosielanie premenných z okolitého (funkčného) rozsahu do tela funkcie lambda výrazu. Telo funkcie výrazu lambda údajne zachytáva premennú, keď prijme objekt. Bez doložky o zachytení [] nemožno premennú odoslať z okolitého rozsahu do tela funkcie lambda výrazu. Nasledujúci program to ilustruje s rozsahom funkcie main () ako okolitým rozsahom:

#zahrnúť

použitím priestor mienhodiny;

intHlavná()

{

intid= 5;


autofn= [id]()

{

náklady <<id<< ' n';

};

fn();


vrátiť sa 0;

}

Výstup je 5 . Bez názvu, id, inside [] by výraz lambda nevidel premennú id rozsahu funkcie main ().

Zachytávanie podľa referencie

Vyššie uvedený príklad použitia doložky o zachytení je zachytenie podľa hodnoty (pozri podrobnosti nižšie). Pri zachytávaní pomocou odkazu je poloha (úložisko) premennej, napr. Id vyššie, okolitého rozsahu dostupná v tele funkcie lambda. Takže zmena hodnoty premennej v tele funkcie lambda zmení hodnotu tej istej premennej v okolitom rozsahu. Aby sa to dosiahlo, každej premennej opakovanej v doložke zachytenia predchádza znak ampersand (&). Nasledujúci program to ilustruje:

#zahrnúť

použitím priestor mienhodiny;

intHlavná()

{

intid= 5; plavákft= 2.3; charch= 'TO';

autofn= [&id,&ft,&ch]()

{

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

};

fn();

náklady <<id<< ',' <<ft<< ',' <<ch<< ' n';

vrátiť sa 0;

}

Výstupom je:

6, 3,4, B

Potvrdzujúc, že ​​názvy premenných v tele funkcie lambda výrazu sú pre rovnaké premenné mimo výrazu lambda.

Zachytenie podľa hodnoty

Pri zachytávaní podľa hodnoty je v tele funkcie lambda k dispozícii kópia umiestnenia premennej a okolitého rozsahu. Aj keď je premenná v tele funkcie lambda kópiou, jej hodnotu nemožno v tele v súčasnosti zmeniť. Aby sa dosiahlo zachytenie podľa hodnoty, každej premennej opakovanej v doložke o zachytení nič nepredchádza. Nasledujúci program to ilustruje:

#zahrnúť

použitím priestor mienhodiny;

intHlavná()

{

intid= 5; plavákft= 2.3; charch= 'TO';

autofn= [id, ft, ch]()

{

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

náklady <<id<< ',' <<ft<< ',' <<ch<< ' n';

};

fn();

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

náklady <<id<< ',' <<ft<< ',' <<ch<< ' n';

vrátiť sa 0;

}

Výstupom je:

5, 2,3, A

6, 3,4, B

Ak je indikátor komentára odstránený, program sa nebude kompilovať. Kompilátor vydá chybové hlásenie, že premenné v definícii výrazu lambda v tele funkcie nemožno zmeniť. Aj keď premenné nemožno meniť vo vnútri funkcie lambda, je možné ich zmeniť aj mimo funkcie lambda, ako ukazuje výstup vyššie uvedeného programu.

Miešanie záberov

Zachytenie pomocou odkazu a zachytenie podľa hodnoty je možné kombinovať, ako ukazuje nasledujúci program:

#zahrnúť

použitím priestor mienhodiny;

intHlavná()

{

intid= 5; plavákft= 2.3; charch= 'TO'; boolbl= pravda;


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

{

ch= 'B';bl= falošný;

náklady <<id<< ',' <<ft<< ',' <<ch<< ',' <<bl<< ' n';

};

fn();


vrátiť sa 0;

}

Výstupom je:

5, 2,3, B, 0

Keď sú všetky zachytené, slúžia ako referencie:

Ak sú všetky premenné, ktoré sa majú zachytiť, zachytené pomocou odkazu, potom v doložke o zachytení postačí iba jedna &. Nasledujúci program to ilustruje:

#zahrnúť

použitím priestor mienhodiny;

intHlavná()

{

intid= 5; plavákft= 2.3; charch= 'TO'; boolbl= pravda;


autofn= [&]()

{

id= 6;ft= 3.4;ch= 'B';bl= falošný;

};

fn();

náklady <<id<< ',' <<ft<< ',' <<ch<< ',' <<bl<< ' n';


vrátiť sa 0;

}

Výstupom je:

6, 3,4, B, 0

Ak majú byť niektoré premenné zachytené odkazom a iné hodnotou, potom jedna & bude predstavovať všetky referencie a zvyšným nebude predchádzať nič, ako ukazuje nasledujúci program:

použitím priestor mienhodiny;

intHlavná()

{

intid= 5; plavákft= 2.3; charch= 'TO'; boolbl= pravda;


autofn= [&, id, ft]()

{

ch= 'B';bl= falošný;

náklady <<id<< ',' <<ft<< ',' <<ch<< ',' <<bl<< ' n';

};

fn();


vrátiť sa 0;

}

Výstupom je:

5, 2,3, B, 0

Všimnite si toho, že & samotný (t. J. & Bez identifikátora) musí byť prvým znakom doložky o zachytení.

Keď sú všetky zachytené, sú zoradené podľa hodnoty:

Ak majú byť všetky premenné, ktoré sa majú zachytiť, zachytené podľa hodnoty, potom v klauzule na zachytenie postačí iba jedna =. Nasledujúci program to ilustruje:

#zahrnúť

použitím priestor mienhodiny;

intHlavná()
{

intid= 5; plavákft= 2.3; charch= 'TO'; boolbl= pravda;


autofn= [=]()

{

náklady <<id<< ',' <<ft<< ',' <<ch<< ',' <<bl<< ' n';

};

fn();


vrátiť sa 0;


}

Výstupom je:

5, 2,3, A, 1

Poznámka : = je zatiaľ len na čítanie.

Ak majú byť niektoré premenné zachytené hodnotou a iné odkazom, potom jedna = bude predstavovať všetky kopírované premenné iba na čítanie a ostatné budú mať &, ako ukazuje nasledujúci program:

#zahrnúť

použitím priestor mienhodiny;

intHlavná()

{

intid= 5; plavákft= 2.3; charch= 'TO'; boolbl= pravda;


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

{

ch= 'B';bl= falošný;

náklady <<id<< ',' <<ft<< ',' <<ch<< ',' <<bl<< ' n';

};

fn();


vrátiť sa 0;

}

Výstupom je:

5, 2,3, B, 0

Všimnite si, že = sám musí byť prvým znakom v doložke o zachytení.

Klasická schéma funkcie spätného volania s lambda výrazom

Nasledujúci program ukazuje, ako je možné vykonať klasickú schému funkcie spätného volania pomocou výrazu lambda:

#zahrnúť

použitím priestor mienhodiny;

char *výkon;


autocba= [](charvon[])

{

výkon=von;

};



prázdnymainFunc(charvstup[],prázdny (*pre)(char[]))

{

(*pre)(vstup);

náklady<<„pre hlavnú funkciu“<<' n';

}


prázdnyfn()

{

náklady<<'Teraz'<<' n';

}


intHlavná()

{

charvstup[] = „pre funkciu spätného volania“;

mainFunc(vstup, cba);

fn();

náklady<<výkon<<' n';



vrátiť sa 0;

}

Výstupom je:

pre hlavnú funkciu

Teraz

pre funkciu spätného volania

Pripomeňme si, že keď je definícii výrazu lambda priradená k premennej v globálnom rozsahu, jeho telo funkcie môže vidieť globálne premenné bez použitia doložky o zachytení.

Typ na konci návratu

Návratový typ výrazu lambda je automatický, čo znamená, že kompilátor určuje návratový typ z návratového výrazu (ak je k dispozícii). Ak chce programátor skutočne uviesť typ návratu, urobí to ako v nasledujúcom programe:

#zahrnúť

použitím priestor mienhodiny;

autofn= [](intzastaviť sa) -> int

{

intodpovedz=zastaviť sa+ 3;

vrátiť saodpovedz;

};


intHlavná()

{

autovariab=fn(2);

náklady <<variab<< ' n';


vrátiť sa 0;

}

Výstup je 5. Po zozname parametrov sa napíše operátor šípky. Nasleduje návratový typ (v tomto prípade int).

Zatvorenie

Zvážte nasledujúci segment kódu:

StructCla

{

intid= 5;

charch= „do“;

}obj1, obj2;

Tu je Cla názov triedy struct. Obj1 a obj2 sú dva objekty, ktorých inštancia bude vytvorená z triedy struct. Lambda výraz je pri implementácii podobný. Definícia funkcie lambda je druh triedy. Keď sa zavolá (vyvolá) funkcia lambda, objekt sa vytvorí inštanciou z jeho definície. Tento objekt sa nazýva uzáver. Je to uzáver, ktorý vykonáva prácu, od ktorej sa očakáva, že lambda bude vykonávať.

Kódovanie výrazu lambda ako vyššie uvedenej štruktúry však bude mať obj1 a obj2 nahradené argumentmi zodpovedajúcich parametrov. Nasledujúci program to ilustruje:

#zahrnúť

použitím priestor mienhodiny;

autofn= [](intparam1,intparam2)

{

intodpovedz=param1+param2;

vrátiť saodpovedz;

} (2,3);


intHlavná()

{

autokde=fn;

náklady <<kde<< ' n';


vrátiť sa 0;

}

Výstup je 5. Argumenty sú 2 a 3 v zátvorkách. Všimnite si toho, že volanie funkcie výrazu lambda fn neberie žiadny argument, pretože argumenty už boli kódované na konci definície funkcie lambda.

Záver

Výraz lambda je anonymná funkcia. Pozostáva z dvoch častí: triedy a objektu. Jeho definícia je druhom triedy. Pri volaní výrazu sa z definície vytvorí predmet. Tento objekt sa nazýva uzáver. Je to uzáver, ktorý vykonáva prácu, od ktorej sa očakáva, že lambda bude vykonávať.

Na to, aby výraz lambda prijal premennú z vonkajšieho rozsahu funkcií, potrebuje do tela svojej funkcie prázdnu doložku zachytávania.