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:
#zahrnoutpomocí 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:
#zahrnoutpomocí 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:
5Mimo 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:
#zahrnoutpomocí 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 5Zde 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:
#zahrnoutpomocí 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:
#zahrnoutpomocí 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, BPotvrzujeme, ž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:
#zahrnoutpomocí 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, A6, 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:
#zahrnoutpomocí 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, 0Když 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:
#zahrnoutpomocí 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, 0Pokud 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, 0Vš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:
#zahrnoutpomocí 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, 1Pozná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:
#zahrnoutpomocí 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, 0Vš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:
#zahrnoutpomocí 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<