C ++

Lambda výrazy v C ++

Lambda výrazy v C ++

Proč lambda výraz?

Zvažte následující prohlášení:

    int myInt = 52;

Zde je myInt identifikátor, hodnota l. 52 je doslovný, prvočíslo. Dnes je možné funkci speciálně kódovat a umístit ji na pozici 52. Takové funkci se říká lambda výraz. Zvažte také následující krátký program:

#zahrnout
pomocí jmenného prostoru std;
int fn (int par)

int odpověď = par + 3;
zpětná odpověď;

int main ()

fn (5);
návrat 0;

Dnes je možné funkci speciálně kódovat a umístit ji do pozice argumentu 5, volání funkce, fn (5). Takové funkci se říká lambda výraz. Výraz lambda (funkce) v této poloze je prvalue.

Jakýkoli literál kromě řetězcového literálu je prvalue. Výraz lambda je návrh speciální funkce, který by se hodil jako literál v kódu. Je to anonymní (nepojmenovaná) funkce. Tento článek vysvětluje nový primární výraz C ++, který se nazývá výraz lambda. Základní znalost jazyka C ++ je podmínkou pro pochopení tohoto článku.

Obsah článku

  • Ilustrace výrazu lambda
  • Části lambda výrazu
  • Zachytává
  • Schéma klasického zpětného volání s výrazem lambda
  • Typ s koncovým návratem
  • Uzavření
  • Závěr

Ilustrace výrazu lambda

V následujícím programu je proměnné přiřazena funkce, která je výrazem lambda:

#zahrnout
pomocí jmenného prostoru std;
auto fn = [] (int param)

int odpověď = param + 3;
zpětná odpověď;
;
int main ()

auto variab = fn (2);
cout << variab << '\n';
návrat 0;

Výstupem je:

    5

Mimo funkci main () existuje proměnná fn. Jeho typ je auto. Auto v této situaci znamená, že skutečný typ, například int nebo float, je určen pravým operandem operátoru přiřazení (=). Na pravé straně operátoru přiřazení je výraz lambda. Výraz lambda je funkce bez předchozího návratového typu. Všimněte si použití a polohy hranatých závorek, []. Funkce vrací 5, int, který určí typ pro fn.

Ve funkci main () je příkaz:

    auto variab = fn (2);

To znamená, že fn mimo main () končí jako identifikátor funkce. Jeho implicitní parametry jsou parametry výrazu lambda. Typ proměnné je auto.

Všimněte si, že výraz lambda končí středníkem, stejně jako definice třídy nebo struktury končí středníkem.

V následujícím programu je funkce, která je výrazem lambda, který vrací hodnotu 5, argumentem pro jinou funkci:

#zahrnout
pomocí jmenného prostoru std;
void otherfn (int no1, int (* ptr) (int))

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

int main ()

otherfn (4, [] (int param)

int odpověď = param + 3;
zpětná odpověď;
);
návrat 0;

Výstupem je:

    4 5

Zde jsou dvě funkce, výraz lambda a funkce otherfn (). Výraz lambda je druhým argumentem otherfn (), volaným v main (). Všimněte si, že funkce lambda (výraz) v tomto volání nekončí středníkem, protože zde jde o argument (ne o samostatnou funkci).

Parametr funkce lambda v definici funkce otherfn () je ukazatel na funkci. Ukazatel má název, ptr. Název ptr se v definici otherfn () používá k volání funkce lambda.

Prohlášení,

    int no2 = (* ptr) (2);

V definici otherfn () volá funkci lambda s argumentem 2. Návratová hodnota volání „(* ptr) (2)“ z funkce lambda je přiřazena č. 2.

Výše uvedený program také ukazuje, jak lze funkci lambda použít ve schématu funkce zpětného volání C ++.

Části lambda výrazu

Části typické funkce lambda jsou následující:

    [] ()
  • [] je doložka o zajetí. Může obsahovat položky.
  • () je pro seznam parametrů.
  • je pro tělo funkce. Pokud je funkce osamocená, měla by končit středníkem.

Zachytává

Definici funkce lambda lze přiřadit k proměnné nebo použít jako argument pro volání jiné funkce. Definice takového volání funkce by měla mít jako parametr ukazatel na funkci odpovídající definici funkce lambda.

Definice funkce lambda se liší od definice normální funkce. Lze jej přiřadit k proměnné v globálním rozsahu; tato funkce přiřazená proměnné může být také kódována uvnitř jiné funkce. Při přiřazení k proměnné globálního rozsahu může její tělo vidět další proměnné v globálním rozsahu. Když je přiřazena proměnné uvnitř definice normální funkce, její tělo může vidět jiné proměnné v rozsahu funkce pouze s pomocí klauzule o zachycení, [].

Klauzule o zachycení [], známá také jako zavaděč lambda, umožňuje odesílání proměnných z okolního (funkčního) rozsahu do těla funkce výrazu lambda. Tělo funkce výrazu lambda se říká, že zachytí proměnnou, když přijme objekt. Bez klauzule o zachycení [] nelze poslat proměnnou z okolního rozsahu do těla funkce výrazu lambda. Následující program to ilustruje s rozsahem funkcí main () jako okolní obor:

#zahrnout
pomocí jmenného prostoru std;
int main ()

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

cout << id << '\n';
;
fn ();
návrat 0;

Výstup je 5. Bez názvu, id, uvnitř [] by výraz lambda neviděl ID proměnné rozsahu funkce main ().

Zachycení pomocí odkazu

Výše uvedené použití klauzule pro zachycení zachycuje podle hodnoty (viz podrobnosti níže). Při zachycení pomocí odkazu je umístění (úložiště) proměnné, např.G., výše uvedené id okolního rozsahu je zpřístupněno uvnitř těla funkce lambda. Takže změna hodnoty proměnné uvnitř těla funkce lambda změní hodnotu téže proměnné v okolním rozsahu. Každá proměnná opakovaná v klauzuli o zachycení předchází znak ampersand (&), aby toho bylo dosaženo. Ilustruje to následující program:

#zahrnout
pomocí jmenného prostoru std;
int main ()

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

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

Výstupem je:

    6, 3.4, B

Potvrzujeme, že názvy proměnných uvnitř těla funkce výrazu lambda jsou pro stejné proměnné mimo výraz lambda.

Zachycení podle hodnoty

Při zachycení podle hodnoty je uvnitř těla funkce lambda zpřístupněna kopie umístění proměnné okolního rozsahu. Přestože proměnná uvnitř těla funkce lambda je kopií, její hodnotu nelze nyní v těle změnit. K dosažení zachycení podle hodnoty nepředchází každé proměnné opakované v klauzuli zachycení nic. Ilustruje to následující program:

#zahrnout
pomocí jmenného prostoru std;
int main ()

int id = 5; float ft = 2.3; char ch = 'A';
auto 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';
návrat 0;

Výstupem je:

5, 2.3, A
6, 3.4, B

Pokud je indikátor komentáře odstraněn, program se nezkompiluje. Kompilátor vydá chybovou zprávu, že proměnné uvnitř definice těla funkce výrazu lambda nelze změnit. Ačkoli proměnné nelze změnit uvnitř funkce lambda, lze je změnit i mimo funkci lambda, jak ukazuje výstup výše uvedeného programu.

Míchání zachycení

Zachycení pomocí odkazu a zachycení podle hodnoty lze kombinovat, jak ukazuje následující program:

#zahrnout
pomocí jmenného prostoru std;
int main ()

int id = 5; float ft = 2.3; char ch = 'A'; bool bl = true;
auto fn = [id, ft, & ch, & bl] ()

ch = 'B'; bl = false;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
návrat 0;

Výstupem je:

    5, 2.3, B, 0

Když jsou všechny zachyceny, jsou odkazem:

Pokud jsou všechny proměnné, které mají být zachyceny, zachyceny odkazem, pak v klauzuli o zachycení postačí pouze jedna &. Ilustruje to následující program:

#zahrnout
pomocí jmenného prostoru std;
int main ()

int id = 5; float ft = 2.3; char ch = 'A'; bool bl = true;
auto fn = [&] ()

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

Výstupem je:

6, 3.4, B, 0

Pokud mají být některé proměnné zachyceny odkazem a jiné hodnotou, pak jedna & bude představovat všechny odkazy a ostatním nebude nic předcházet, jak ukazuje následující program:

pomocí jmenného prostoru std;
int main ()

int id = 5; float ft = 2.3; char ch = 'A'; bool bl = true;
auto fn = [&, id, ft] ()

ch = 'B'; bl = false;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
návrat 0;

Výstupem je:

5, 2.3, B, 0

Všimněte si, že & sám (tj.E., & nenásleduje identifikátor) musí být prvním znakem v klauzuli o zachycení.

Když jsou všechny zachyceny, jsou podle hodnoty:

Pokud mají být všechny proměnné, které mají být zachyceny, zachyceny podle hodnoty, bude v klauzuli o zachycení stačit pouze jedna =. Ilustruje to následující program:

#zahrnout
pomocí jmenného prostoru std;
int main ()

int id = 5; float ft = 2.3; char ch = 'A'; bool bl = true;
auto fn = [=] ()

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

Výstupem je:

5, 2.3, A, 1

Poznámka: = je od teď jen pro čtení.

Pokud mají být některé proměnné zachyceny hodnotou a jiné odkazem, pak jedna = bude představovat všechny kopírované proměnné jen pro čtení a zbytek bude mít &, jak ukazuje následující program:

#zahrnout
pomocí jmenného prostoru std;
int main ()

int id = 5; float ft = 2.3; char ch = 'A'; bool bl = true;
auto fn = [=, & ch, & bl] ()

ch = 'B'; bl = false;
cout << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
fn ();
návrat 0;

Výstupem je:

5, 2.3, B, 0

Všimněte si, že = sám musí být prvním znakem v klauzuli zachycení.

Schéma klasického zpětného volání s výrazem lambda

Následující program ukazuje, jak lze provést klasické schéma funkce zpětného volání s výrazem lambda:

#zahrnout
pomocí jmenného prostoru std;
char * výstup;
auto cba = [] (char out [])

výstup = ven;
;
void principalFunc (char input [], void (* pt) (char []))

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

void fn ()

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

int main ()

char input [] = "pro funkci zpětného volání";
principalFunc (vstup, cba);
fn ();
cout<návrat 0;

Výstupem je:

pro hlavní funkci
Nyní
pro funkci zpětného volání

Připomeňme, že když je definice výrazu lambda přiřazena proměnné v globálním rozsahu, její tělo funkce může vidět globální proměnné bez použití klauzule zachycení.

Typ s koncovým návratem

Návratový typ výrazu lambda je auto, což znamená, že kompilátor určuje návratový typ z návratového výrazu (je-li k dispozici). Pokud programátor opravdu chce označit návratový typ, udělá to jako v následujícím programu:

#zahrnout
pomocí jmenného prostoru std;
auto fn = [] (int param) -> int

int odpověď = param + 3;
zpětná odpověď;
;
int main ()

auto variab = fn (2);
cout << variab << '\n';
návrat 0;

Výstup je 5. Po seznamu parametrů je zadán operátor šipky. Poté následuje návratový typ (v tomto případě int).

Uzavření

Zvažte následující segment kódu:

struktura Cla

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

Zde je Cla název třídy struktury.  Obj1 a obj2 jsou dva objekty, které budou vytvořeny z třídy struktur. Lambda výraz je podobný v implementaci. Definice funkce lambda je druh třídy. Když je funkce lambda volána (vyvolána), objekt je vytvořen z jeho definice. Tento objekt se nazývá uzávěr. Je to uzávěr, který dělá práci, od které se lambda očekává.

Avšak při kódování výrazu lambda, jako je výše uvedená struktura, budou obj1 a obj2 nahrazeny argumenty odpovídajících parametrů. Ilustruje to následující program:

#zahrnout
pomocí jmenného prostoru std;
auto fn = [] (int param1, int param2)

int odpověď = param1 + param2;
zpětná odpověď;
(2, 3);
int main ()

auto var = fn;
cout << var << '\n';
návrat 0;

Výstup je 5. Argumenty jsou 2 a 3 v závorkách. Všimněte si, že volání funkce výrazu lambda, fn, nebere žádný argument, protože argumenty již byly kódovány na konci definice funkce lambda.

Závěr

Výraz lambda je anonymní funkce. Skládá se ze dvou částí: třídy a objektu. Jeho definice je jakousi třídou. Při volání výrazu je objekt vytvořen z definice. Tento objekt se nazývá uzávěr. Je to uzávěr, který dělá práci, od které se lambda očekává.

Aby výraz lambda přijímal proměnnou z vnějšího rozsahu funkcí, potřebuje do svého těla funkce neprázdnou klauzuli zachycení.

WinMouse vám umožňuje přizpůsobit a vylepšit pohyb ukazatele myši na PC s Windows
Chcete-li vylepšit výchozí funkce ukazatele myši, použijte freeware WinMouse. Přidává další funkce, které vám pomohou vytěžit ze své skromné ​​myši ma...
V systému Windows 10 nefunguje levé tlačítko myši
Pokud používáte speciální myš s notebookem nebo stolním počítačem, ale levé tlačítko myši nefunguje ve Windows 10/8/7 z nějakého důvodu uvádíme několi...
Kurzor při psaní v systému Windows 10 skáče nebo se pohybuje náhodně
Pokud zjistíte, že kurzor myši skáče nebo se pohybuje sám, automaticky, náhodně při psaní v notebooku nebo počítači se systémem Windows, pak vám někte...