Ц ++

Ламбда изрази у језику Ц ++

Ламбда изрази у језику Ц ++

Зашто Ламбда израз?

Размотрите следећу изјаву:

    инт миИнт = 52;

Овде је миИнт идентификатор, вредност. 52 је дословно, прва вредност. Данас је могуће посебно кодирати функцију и ставити је у положај 52. Таква функција назива се ламбда израз. Узмите у обзир и следећи кратки програм:

#инцлуде
коришћење простора имена стд;
инт фн (инт пар)

инт одговор = пар + 3;
одговор на повратак;

инт маин ()

фн (5);
ретурн 0;

Данас је могуће посебно кодирати функцију и ставити је у положај аргумента 5, позива функције, фн (5). Таква функција назива се ламбда израз. Ламбда израз (функција) у том положају је прва вредност.

Било који литерал осим литералног низа је прва вредност. Ламбда израз је посебан дизајн функције који би одговарао као дословном коду. То је анонимна (неименована) функција. Овај чланак објашњава нови примарни израз Ц ++, назван ламбда израз. Основно знање на језику Ц ++ је услов за разумевање овог чланка.

Садржај чланка

  • Илустрација Ламбда израза
  • Делови Ламбда израза
  • Хватања
  • Класична шема функције повратног позива са Ламбда изразом
  • Тип пратећег повратка
  • Затварање
  • Закључак

Илустрација Ламбда израза

У следећем програму, променљивој је додељена функција, која је ламбда израз:

#инцлуде
коришћење простора имена стд;
ауто фн = [] (инт парам)

инт одговор = парам + 3;
одговор на повратак;
;
инт маин ()

ауто вариаб = фн (2);
цоут << variab << '\n';
ретурн 0;

Излаз је:

    5

Изван главне () функције налази се променљива фн. Његова врста је ауто. Аутоматски у овој ситуацији значи да је стварни тип, као што је инт или флоат, одређен десним операндом оператора доделе (=). Десно од оператора доделе налази се ламбда израз. Ламбда израз је функција без претходног типа повратка. Обратите пажњу на употребу и положај углатих заграда, []. Функција враћа 5, инт, који ће одредити тип за фн.

У функцији маин () налази се изјава:

    ауто вариаб = фн (2);

То значи да фн изван маин () завршава као идентификатор функције. Његови имплицитни параметри су параметри ламбда израза. Тип за варијаб је аутоматски.

Имајте на уму да се ламбда израз завршава тачком и зарезом, баш као што се дефиниција класе или структуре завршава тачком и зарезом.

У следећем програму, функција, која је ламбда израз који враћа вредност 5, је аргумент другој функцији:

#инцлуде
коришћење простора имена стд;
воид отхерфн (инт бр1, инт (* птр) (инт))

инт бр2 = (* птр) (2);
цоут << no1 << " << no2 << '\n';

инт маин ()

отхерфн (4, [] (инт парам)

инт одговор = парам + 3;
одговор на повратак;
);
ретурн 0;

Излаз је:

    4 5

Овде постоје две функције, ламбда израз и функција отхерфн (). Ламбда израз је други аргумент отхерфн (), позван у маин (). Имајте на уму да се ламбда функција (израз) не завршава тачком и зарезом у овом позиву јер је овде аргумент (а не самостална функција).

Параметар ламбда функције у дефиницији функције отхерфн () је показивач на функцију. Показивач има име, птр. Име, птр, користи се у дефиницији отхерфн () за позивање ламбда функције.

Изјава,

    инт бр2 = (* птр) (2);

У дефиницији отхерфн (), позива ламбда функцију са аргументом 2. Повратна вредност позива, "(* птр) (2)" из ламбда функције, додељује се но2.

Горњи програм такође показује како се ламбда функција може користити у шеми функција повратног позива Ц ++.

Делови Ламбда израза

Делови типичне ламбда функције су следећи:

    [] ()
  • [] је клаузула за хватање. Може имати предмете.
  • () је за листу параметара.
  • је за тело функције. Ако функција стоји самостално, требало би да се завршава тачком и зарезом.

Хватања

Дефиниција ламбда функције може се доделити променљивој или користити као аргумент другом позиву функције. Дефиниција за такав позив функције треба да има као параметар показивач на функцију, који одговара дефиницији ламбда функције.

Дефиниција ламбда функције разликује се од нормалне дефиниције функције. Може се доделити променљивој у глобалном опсегу; ова функција додељена променљивој такође се може кодирати унутар друге функције. Када је додељено глобалној променљивој опсега, његово тело може видети друге променљиве у глобалном опсегу. Када је додељено променљивој унутар нормалне дефиниције функције, њено тело може видети друге променљиве у опсегу функције само уз помоћ клаузуле за хватање, [].

Клаузула за хватање [], позната и као ламбда-уводник, омогућава слање променљивих из околног (функцијског) опсега у тело функције ламбда израза. Каже се да тело функције ламбда израза захвата променљиву када прими објекат. Без клаузуле цаптуре [] променљива се не може послати из околног опсега у тело функције ламбда израза. Следећи програм то илуструје са опсегом функције маин () као околним опсегом:

#инцлуде
коришћење простора имена стд;
инт маин ()

инт ид = 5;
ауто фн = [ид] ()

цоут << id << '\n';
;
фн ();
ретурн 0;

Излаз је 5. Без имена, ид, унутар [], ламбда израз не би видео променљиву ид опсега функције маин ().

Снимање помоћу референце

Горњи пример употребе клаузуле цаптуре је хватање по вредности (погледајте детаље у наставку). Приликом снимања путем референце, локација (складиште) променљиве, нпр.г., ид горе, опсега окружења, доступан је унутар тела ламбда функције. Дакле, промена вредности променљиве унутар тела ламбда функције промениће вредност те исте променљиве у околном опсегу. Свакој променљивој поновљеној у клаузули за хватање претходи знак & (&) да би се то постигло. Следећи програм то илуструје:

#инцлуде
коришћење простора имена стд;
инт маин ()

инт ид = 5; флоат фт = 2.3; цхар цх = 'А';
ауто фн = [& ид, & фт, & цх] ()

ид = 6; фт = 3.4; цх = 'Б';
;
фн ();
цоут << id << ", " <<  ft << ", " <<  ch << '\n';
ретурн 0;

Излаз је:

    6, 3.4, Б

Потврђујући да су имена променљивих унутар тела функције ламбда израза за исте променљиве изван ламбда израза.

Хватање по вредности

Приликом хватања по вредности, копија локације променљиве, околног опсега, доступна је унутар тела ламбда функције. Иако је променљива унутар тела ламбда функције копија, њена вредност од сада не може да се мења у телу. Да би се постигло хватање по вредности, свакој променљивој која се понавља у клаузули за хватање не претходи ништа. Следећи програм то илуструје:

#инцлуде
коришћење простора имена стд;
инт маин ()

инт ид = 5; флоат фт = 2.3; цхар цх = 'А';
аутоматски фн = [ид, фт, цх] ()

// ид = 6; фт = 3.4; цх = 'Б';
цоут << id << ", " <<  ft << ", " <<  ch << '\n';
;
фн ();
ид = 6; фт = 3.4; цх = 'Б';
цоут << id << ", " <<  ft << ", " <<  ch << '\n';
ретурн 0;

Излаз је:

5, 2.3, А
6, 3.4, Б

Ако се уклони индикатор коментара, програм се неће компајлирати. Преводник ће издати поруку о грешци да променљиве унутар дефиниције тела функције ламбда израза не могу бити промењене. Иако се променљиве не могу мењати унутар ламбда функције, оне се могу мењати изван ламбда функције, као што показује горњи излаз програма.

Мешање снимака

Снимање помоћу референце и хватање по вредности може се мешати, као што показује следећи програм:

#инцлуде
коришћење простора имена стд;
инт маин ()

инт ид = 5; флоат фт = 2.3; цхар цх = 'А'; боол бл = тачно;
аутоматски фн = [ид, фт, & цх, & бл] ()

цх = 'Б'; бл = нетачно;
цоут << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
фн ();
ретурн 0;

Излаз је:

    5, 2.3, Б, 0

Када су сви заробљени, референцом су:

Ако су све променљиве које треба ухватити ухваћене референцом, тада ће у клаузули за хватање бити довољна само једна &. Следећи програм то илуструје:

#инцлуде
коришћење простора имена стд;
инт маин ()

инт ид = 5; флоат фт = 2.3; цхар цх = 'А'; боол бл = тачно;
аутоматски фн = [&] ()

ид = 6; фт = 3.4; цх = 'Б'; бл = нетачно;
;
фн ();
цоут << id << ", " << ft << ", " << ch << ", " << bl << '\n';
ретурн 0;

Излаз је:

6, 3.4, Б, 0

Ако ће неке променљиве бити забележене референцом, а друге вредностом, тада ће једна & представљати све референце, а осталима неће ништа претходити, као што показује следећи програм:

коришћење простора имена стд;
инт маин ()

инт ид = 5; флоат фт = 2.3; цхар цх = 'А'; боол бл = тачно;
аутоматски фн = [&, ид, фт] ()

цх = 'Б'; бл = нетачно;
цоут << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
фн ();
ретурн 0;

Излаз је:

5, 2.3, Б, 0

Имајте на уму да & сам (и.е., и не прати га идентификатор) мора бити први знак у клаузули за снимање.

Када су све забележене, вредности су:

Ако све променљиве које треба ухватити треба да буду забележене по вредности, тада ће у клаузули за хватање бити довољан само један =. Следећи програм то илуструје:

#инцлуде
коришћење простора имена стд;
инт маин ()

инт ид = 5; флоат фт = 2.3; цхар цх = 'А'; боол бл = тачно;
аутоматски фн = [=] ()

цоут << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
фн ();
ретурн 0;

Излаз је:

5, 2.3, А, 1

Белешка: = од сада је само за читање.

Ако неке променљиве треба ухватити по вредности, а друге по референци, тада ће једна = представљати све копиране променљиве само за читање, а остале ће имати &, као што показује следећи програм:

#инцлуде
коришћење простора имена стд;
инт маин ()

инт ид = 5; флоат фт = 2.3; цхар цх = 'А'; боол бл = тачно;
аутоматски фн = [=, & цх, & бл] ()

цх = 'Б'; бл = нетачно;
цоут << id << ", " << ft << ", " << ch << ", " << bl << '\n';
;
фн ();
ретурн 0;

Излаз је:

5, 2.3, Б, 0

Имајте на уму да = алоне мора бити први знак у клаузули за снимање.

Класична шема функције повратног позива са Ламбда изразом

Следећи програм показује како се класична шема функције повратног позива може урадити са ламбда изразом:

#инцлуде
коришћење простора имена стд;
цхар * излаз;
аутоматски цба = [] (исцртавање [])

оутпут = оут;
;
воид принципалФунц (цхар инпут [], воид (* пт) (цхар []))

(* пт) (улаз);
цоут<<"for principal function"<<'\n';

воид фн ()

цоут<<"Now"<<'\n';

инт маин ()

цхар инпут [] = "за функцију повратног позива";
принципалФунц (инпут, цба);
фн ();
цоут<ретурн 0;

Излаз је:

за главну функцију
Сада
за функцију повратног позива

Подсетимо се да када је дефиниција ламбда израза додељена променљивој у глобалном опсегу, њено тело функције може видети глобалне променљиве без употребе клаузуле цаптуре.

Тип пратећег повратка

Тип повратка ламбда израза је аутоматски, што значи да компајлер одређује тип повратка из израза ретурн (ако је присутан). Ако програмер заиста жели да наведе тип повратка, то ће учинити као у следећем програму:

#инцлуде
коришћење простора имена стд;
ауто фн = [] (инт парам) -> инт

инт одговор = парам + 3;
одговор на повратак;
;
инт маин ()

ауто вариаб = фн (2);
цоут << variab << '\n';
ретурн 0;

Излаз је 5. Након листе параметара укуцава се оператор стрелице. Након тога следи тип повратка (у овом случају инт).

Затварање

Размотрите следећи сегмент кода:

струцт Цла

инт ид = 5;
цхар цх = 'а';
обј1, обј2;

Овде је Цла назив класе струцт.  Обј1 и обј2 су два објекта која ће бити покренута из класе струцт. Ламбда израз је сличан у примени. Дефиниција ламбда функције је нека врста класе. Када се ламбда функција позове (позове), објект се инстанцира из њене дефиниције. Овај објекат назива се затварање. Затварање чини оно што се очекује од ламбде.

Међутим, кодирање ламбда израза попут горње структуре ће имати обј1 и обј2 замењене аргументима одговарајућих параметара. Следећи програм то илуструје:

#инцлуде
коришћење простора имена стд;
ауто фн = [] (инт парам1, инт парам2)

инт одговор = парам1 + парам2;
одговор на повратак;
(2, 3);
инт маин ()

ауто вар = фн;
цоут << var << '\n';
ретурн 0;

Излаз је 5. Аргументи су 2 и 3 у заградама. Имајте на уму да позив функције ламбда израза, фн, не узима ниједан аргумент јер су аргументи већ кодирани на крају дефиниције ламбда функције.

Закључак

Ламбда израз је анонимна функција. Састоји се из два дела: класе и објекта. Његова дефиниција је врста класе. Када се израз позове, из дефиниције се формира објекат. Овај објекат назива се затварање. Затварање чини оно што се очекује од ламбде.

Да би ламбда израз примио променљиву из спољног опсега функције, потребна му је непразна клаузула за хватање у своје тело функције.

Емулирајте кликове мишем лебдењем помоћу миша без клика у оперативном систему Виндовс 10
Коришћење миша или тастатуре у погрешном положају прекомерне употребе може резултирати многим здравственим проблемима, укључујући напрезање, синдром к...
Додајте покрете миша у Виндовс 10 помоћу ових бесплатних алата
Последњих година рачунари и оперативни системи су се увелико развили. Било је време када су корисници морали да користе команде за навигацију кроз мен...
Контролишите и управљајте кретањем миша између више монитора у оперативном систему Виндовс 10
Двоструки приказ миша омогућава вам контролу и конфигурисање кретања миша између више монитора, успоравајући његово кретање близу границе. Виндовс 10/...