Mga Lambda Expression sa C ++

Lambda Expressions C



Bakit Lambda Expression?

Isaalang-alang ang sumusunod na pahayag:

intmyInt= 52;

Dito, ang myInt ay isang identifier, isang lvalue. Ang 52 ay isang literal, isang prvalue. Ngayon, posible na mag-code ng isang pagpapaandar lalo na at ilagay ito sa posisyon na 52. Ang nasabing pagpapaandar ay tinatawag na isang expression ng lambda. Isaalang-alang din ang sumusunod na maikling programa:







# isama

gamit namespaceoras;

intfn(intsa pamamagitan ng)

{

intsagot=sa pamamagitan ng+ 3;

bumalik kasagot;

}


intpangunahing()

{

fn(5);



bumalik ka 0;

}

Ngayon, posible na mag-code ng espesyal na pag-andar at ilagay ito sa posisyon ng argumento ng 5, ng function call, fn (5). Ang ganitong pag-andar ay tinatawag na isang expression ng lambda. Ang expression ng lambda (pagpapaandar) sa posisyon na iyon ay isang prvalue.



Anumang literal maliban sa string na literal ay isang prvalue. Ang expression ng lambda ay isang espesyal na disenyo ng pagpapaandar na magkasya bilang isang literal sa code. Ito ay isang hindi nagpapakilala (hindi pinangalanan) na pagpapaandar. Ipinapaliwanag ng artikulong ito ang bagong pangunahing expression ng C ++, na tinatawag na lambda expression. Ang pangunahing kaalaman sa C ++ ay isang kinakailangan upang maunawaan ang artikulong ito.



Nilalaman ng Artikulo

Paglalarawan ng Lambda Expression

Sa sumusunod na programa, ang isang pagpapaandar, na isang expression ng lambda, ay nakatalaga sa isang variable:





# isama

gamit namespaceoras;

awtomatikofn= [](inthuminto ka)

{

intsagot=huminto ka+ 3;

bumalik kasagot;

};


intpangunahing()

{

awtomatikovariab=fn(2);

gastos <<variab<< ' n';


bumalik ka 0;

}

Ang output ay:

5

Sa labas ng pangunahing () pagpapaandar, mayroong variable, fn. Ang uri nito ay awtomatiko. Ang auto sa sitwasyong ito ay nangangahulugang ang aktwal na uri, tulad ng int o float, ay natutukoy ng tamang operand ng operator ng pagtatalaga (=). Sa kanan ng operator ng pagtatalaga ay isang expression ng lambda. Ang isang expression ng lambda ay isang pagpapaandar nang walang naunang uri ng pagbabalik. Tandaan ang paggamit at posisyon ng mga square bracket, []. Ang pagpapaandar ay nagbabalik ng 5, isang int, na tutukoy sa uri para sa fn.



Sa pangunahing () pagpapaandar, mayroong pahayag:

awtomatikovariab=fn(2);

Nangangahulugan ito, fn sa labas ng pangunahing (), nagtatapos bilang tagapagpakilala para sa isang pagpapaandar. Ang mga ipinahiwatig na parameter nito ay ang ekspresyon ng lambda. Ang uri para sa variab ay awtomatiko.

Tandaan na ang expression ng lambda ay nagtatapos sa isang kalahating titik, tulad ng klase o kahulugan ng istruktura, nagtatapos sa isang kalahating titik.

Sa sumusunod na programa, ang isang pagpapaandar, na isang expression ng lambda na nagbabalik ng halaga ng 5, ay isang argument sa ibang pagpapaandar:

# isama

gamit namespaceoras;

walang bisaotherfn(intno1,int (*ptr)(int))

{

inthindi2= (*ptr)(2);

gastos <<no1<< ' <<hindi2<< ' n';

}


intpangunahing()

{

otherfn(4,[](inthuminto ka)

{

intsagot=huminto ka+ 3;

bumalik kasagot;

});


bumalik ka 0;
}

Ang output ay:

Apat lima

Mayroong dalawang pagpapaandar dito, ang ekspresyon ng lambda at ang paggana ng otherfn (). Ang expression ng lambda ay ang pangalawang argumento ng otherfn (), na tinatawag na pangunahing (). Tandaan na ang pag-andar ng lambda (expression) ay hindi nagtatapos sa isang kalahating titik sa tawag na ito dahil, narito, ito ay isang argument (hindi isang pag-andar na nag-iisa).

Ang parameter ng pagpapaandar ng lambda sa kahulugan ng otherfn () na pagpapaandar ay isang pointer sa isang pagpapaandar. Ang pointer ay may pangalan, ptr. Ang pangalan, ptr, ay ginagamit sa ibang kahulugan ng (f) upang tawagan ang lambda function.

Ang pahayag,

inthindi2= (*ptr)(2);

Sa kahulugan ng otherfn (), tinawag nito ang pagpapaandar ng lambda na may argument na 2. Ang halaga ng pagbalik ng tawag, '(* ptr) (2)' mula sa pag-andar ng lambda, ay nakatalaga sa no2.

Ipinapakita rin ng program sa itaas kung paano magagamit ang pag-andar ng lambda sa C ++ callback function scheme.

Mga Bahagi ng Lambda Expression

Ang mga bahagi ng isang karaniwang pag-andar ng lambda ay ang mga sumusunod:

[] () {}
  • [] ay ang sugnay na kuha. Maaari itong magkaroon ng mga item.
  • Ang () ay para sa listahan ng parameter.
  • Ang {} ay para sa body ng pag-andar. Kung ang pag-andar ay nakatayo nang nag-iisa, dapat itong magtapos sa isang kalahating titik.

Nakunan

Ang kahulugan ng pag-andar ng lambda ay maaaring italaga sa isang variable o ginamit bilang argument sa ibang tawag sa pagpapaandar. Ang kahulugan para sa isang tawag na tulad ng pag-andar ay dapat magkaroon ng isang parameter, isang pointer sa isang pagpapaandar, na naaayon sa kahulugan ng pag-andar ng lambda.

Ang kahulugan ng pag-andar ng lambda ay naiiba mula sa normal na kahulugan ng pagpapaandar. Maaari itong italaga sa isang variable sa pandaigdigang saklaw; ang function na itinalaga-sa-variable na ito ay maaari ring naka-code sa loob ng isa pang pagpapaandar. Kapag nakatalaga sa isang pandaigdigang variable ng saklaw, ang katawan nito ay maaaring makakita ng iba pang mga variable sa pandaigdigang saklaw. Kapag naitalaga sa isang variable sa loob ng isang normal na kahulugan ng pag-andar, ang katawan nito ay makakakita ng iba pang mga variable sa saklaw ng pag-andar lamang sa tulong ng klausa ng pagkuha, [].

Ang sugnay na kuha [], na kilala rin bilang tagapagpakilala ng lambda, ay nagbibigay-daan sa mga variable na maipadala mula sa nakapalibot na (pag-andar) saklaw sa katawan ng pag-andar ng lambda expression. Ang body function ng lambda expression ay sinasabing nakakuha ng variable kapag natanggap nito ang bagay. Nang walang sugnay na pang-capture [], hindi maipapadala ang isang variable mula sa nakapaligid na saklaw sa katawan ng pag-andar ng lambda expression. Ang sumusunod na programa ay naglalarawan nito, na may pangunahing () saklaw ng pag-andar, tulad ng nakapalibot na saklaw:

# isama

gamit namespaceoras;

intpangunahing()

{

intid= 5;


awtomatikofn= [id]()

{

gastos <<id<< ' n';

};

fn();


bumalik ka 0;

}

Ang output ay 5 . Kung wala ang pangalan, id, sa loob ng [], ang expression ng lambda ay hindi makikita ang variable id ng pangunahing () saklaw ng pag-andar.

Nakukuha sa pamamagitan ng Sanggunian

Ang halimbawang paggamit ng cluse ng kuha ay nakakakuha ng halaga (tingnan ang mga detalye sa ibaba). Sa pagkuha sa pamamagitan ng sanggunian, ang lokasyon (imbakan) ng variable, hal., Id sa itaas, ng nakapalibot na saklaw, ay ginawang magagamit sa loob ng lambda function na katawan. Kaya, ang pagbabago ng halaga ng variable sa loob ng lambda function na katawan ay magbabago ng halaga ng parehong variable sa nakapaligid na saklaw. Ang bawat variable na paulit-ulit sa cluse ng pagkuha ay naunahan ng ampersand (&) upang makamit ito. Inilalarawan ito ng sumusunod na programa:

# isama

gamit namespaceoras;

intpangunahing()

{

intid= 5; lumutangft= 2.3; charch= 'TO';

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

{

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

};

fn();

gastos <<id<< ',' <<ft<< ',' <<ch<< ' n';

bumalik ka 0;

}

Ang output ay:

6, 3.4, B

Kinukumpirma na ang mga variable na pangalan sa loob ng body function ng lambda expression ay para sa parehong variable sa labas ng expression ng lambda.

Nakukuha ayon sa Halaga

Sa pagkuha sa pamamagitan ng halaga, isang kopya ng lokasyon ng variable, ng nakapaligid na saklaw, ay magagamit sa loob ng lambda function na katawan. Kahit na ang variable sa loob ng lambda function na katawan ay isang kopya, ang halaga nito ay hindi mababago sa loob ng katawan tulad ng ngayon. Upang makamit ang pagkuha sa pamamagitan ng halaga, ang bawat variable na paulit-ulit sa cluse ng pagkuha ay hindi naunahan ng anumang bagay. Inilalarawan ito ng sumusunod na programa:

# isama

gamit namespaceoras;

intpangunahing()

{

intid= 5; lumutangft= 2.3; charch= 'TO';

awtomatikofn= [id, ft, ch]()

{

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

gastos <<id<< ',' <<ft<< ',' <<ch<< ' n';

};

fn();

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

gastos <<id<< ',' <<ft<< ',' <<ch<< ' n';

bumalik ka 0;

}

Ang output ay:

5, 2.3, A

6, 3.4, B

Kung tinanggal ang tagapagpahiwatig ng komento, ang programa ay hindi makakaipon. Maglalabas ang tagatala ng isang mensahe ng error na ang mga variable sa loob ng kahulugan ng body function ng expression ng lambda ay hindi mababago. Bagaman hindi mababago ang mga variable sa loob ng pag-andar ng lambda, maaari silang mabago sa labas ng lambda function, tulad ng ipinakita na output ng programa sa itaas.

Mga Halo ng Paghahalo

Ang paghuli sa pamamagitan ng sanggunian at pagkuha ng ayon sa halaga ay maaaring ihalo, tulad ng ipinapakita ng sumusunod na programa:

# isama

gamit namespaceoras;

intpangunahing()

{

intid= 5; lumutangft= 2.3; charch= 'TO'; boolbl= totoo;


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

{

ch= 'B';bl= hindi totoo;

gastos <<id<< ',' <<ft<< ',' <<ch<< ',' <<bl<< ' n';

};

fn();


bumalik ka 0;

}

Ang output ay:

5, 2.3, B, 0

Kapag ang lahat ay nakuha, ay sa pamamagitan ng sanggunian:

Kung ang lahat ng mga variable na makukuha ay nakunan ng sanggunian, pagkatapos ay isa lamang at magkakaroon ng sapat sa klausa ng pagkuha. Inilalarawan ito ng sumusunod na programa:

# isama

gamit namespaceoras;

intpangunahing()

{

intid= 5; lumutangft= 2.3; charch= 'TO'; boolbl= totoo;


awtomatikofn= [&]()

{

id= 6;ft= 3.4;ch= 'B';bl= hindi totoo;

};

fn();

gastos <<id<< ',' <<ft<< ',' <<ch<< ',' <<bl<< ' n';


bumalik ka 0;

}

Ang output ay:

6, 3.4, B, 0

Kung ang ilang mga variable ay maaaring makuha sa pamamagitan ng sanggunian at ang iba ayon sa halaga, pagkatapos ang isa at ay kumakatawan sa lahat ng mga sanggunian, at ang natitira ay bawat isa ay hindi mauunahan ng anupaman, tulad ng ipinapakita ng sumusunod na programa:

gamit namespaceoras;

intpangunahing()

{

intid= 5; lumutangft= 2.3; charch= 'TO'; boolbl= totoo;


awtomatikofn= [&, id, ft]()

{

ch= 'B';bl= hindi totoo;

gastos <<id<< ',' <<ft<< ',' <<ch<< ',' <<bl<< ' n';

};

fn();


bumalik ka 0;

}

Ang output ay:

5, 2.3, B, 0

Tandaan na ang at nag-iisa (ibig sabihin, at hindi sinusundan ng isang tagakilala) ay dapat na ang unang character sa klausa ng pagkuha.

Kapag nakuha ang lahat, ayon sa halaga:

Kung ang lahat ng mga variable na makukuha ay makunan ng halaga, pagkatapos ang isa lamang = ay sasapat sa parusang pang-capture. Inilalarawan ito ng sumusunod na programa:

# isama

gamit namespaceoras;

intpangunahing()
{

intid= 5; lumutangft= 2.3; charch= 'TO'; boolbl= totoo;


awtomatikofn= [=]()

{

gastos <<id<< ',' <<ft<< ',' <<ch<< ',' <<bl<< ' n';

};

fn();


bumalik ka 0;


}

Ang output ay:

5, 2.3, A, 1

Tandaan : = ay read-only, hanggang ngayon.

Kung ang ilang mga variable ay maaaring makuha ng halaga at ang iba sa pamamagitan ng sanggunian, pagkatapos ang isa = ay kumakatawan sa lahat ng mga nabasa lamang na kinopyang mga variable, at ang natitira ay magkakaroon ng bawat isa &, tulad ng ipinapakita ng sumusunod na programa:

# isama

gamit namespaceoras;

intpangunahing()

{

intid= 5; lumutangft= 2.3; charch= 'TO'; boolbl= totoo;


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

{

ch= 'B';bl= hindi totoo;

gastos <<id<< ',' <<ft<< ',' <<ch<< ',' <<bl<< ' n';

};

fn();


bumalik ka 0;

}

Ang output ay:

5, 2.3, B, 0

Tandaan na = nag-iisa ay dapat na ang unang character sa ang sugnay na kuha.

Classical Callback Function Scheme na may Lambda Expression

Ipinapakita ng sumusunod na programa kung paano magagawa ang isang klasikal na scheme ng pagpapaandar ng callback na may lambda expression:

# isama

gamit namespaceoras;

char *output;


awtomatikocba= [](charpalabas[])

{

output=palabas;

};



walang bisamainFunc(charinput[],walang bisa (*para sa)(char[]))

{

(*para sa)(input);

gastos<<'para sa pangunahing pagpapaandar'<<' n';

}


walang bisafn()

{

gastos<<'Ngayon'<<' n';

}


intpangunahing()

{

charinput[] = 'para sa pagpapaandar ng callback';

mainFunc(input, cba);

fn();

gastos<<output<<' n';



bumalik ka 0;

}

Ang output ay:

para sa pangunahing pagpapaandar

Ngayon

para sa pagpapaandar ng callback

Alalahanin na kapag ang isang kahulugan ng expression ng lambda ay itinalaga sa isang variable sa pandaigdigang saklaw, ang katawan ng pag-andar nito ay maaaring makakita ng mga variable sa buong mundo nang hindi gumagamit ng sugnay na pang-capture.

Ang trailing-return-type

Ang uri ng pagbabalik ng isang expression ng lambda ay awtomatiko, nangangahulugang tinutukoy ng tagatala ang uri ng pagbabalik mula sa ekspresyon ng pagbabalik (kung mayroon). Kung nais talagang ipahiwatig ng programmer ang uri ng pagbabalik, gagawin niya ito tulad ng sa sumusunod na programa:

# isama

gamit namespaceoras;

awtomatikofn= [](inthuminto ka) -> int

{

intsagot=huminto ka+ 3;

bumalik kasagot;

};


intpangunahing()

{

awtomatikovariab=fn(2);

gastos <<variab<< ' n';


bumalik ka 0;

}

Ang output ay 5. Pagkatapos ng listahan ng parameter, na-type ang arrow operator. Sinusundan ito ng uri ng pagbabalik (int sa kasong ito).

Pagsasara

Isaalang-alang ang sumusunod na segment ng code:

istrukturaCla

{

intid= 5;

charch= 'to';

}obj1, obj2;

Dito, Cla ang pangalan ng stras ng klase. Ang Obj1 at obj2 ay dalawang bagay na maitatag mula sa istrukturang klase. Ang expression ng lambda ay pareho sa pagpapatupad. Ang kahulugan ng pag-andar ng lambda ay isang uri ng klase. Kapag ang lambda function ay tinawag na (invoking), isang bagay ay instantiated mula sa kahulugan nito. Ang bagay na ito ay tinatawag na isang pagsasara. Ito ang pagsasara na gumagawa ng gawaing inaasahan na gawin ng lambda.

Gayunpaman, ang pag-coding ng expression ng lambda tulad ng struct sa itaas ay magkakaroon ng obj1 at obj2 na pinalitan ng mga katugmang parameter ’na mga argumento. Inilalarawan ito ng sumusunod na programa:

# isama

gamit namespaceoras;

awtomatikofn= [](intparam1,intparam2)

{

intsagot=param1+param2;

bumalik kasagot;

} (2,3);


intpangunahing()

{

awtomatikokung saan=fn;

gastos <<kung saan<< ' n';


bumalik ka 0;

}

Ang output ay 5. Ang mga argumento ay 2 at 3 sa panaklong. Tandaan na ang lambda expression function call, fn, ay hindi kumukuha ng anumang argumento dahil ang mga argumento ay nai-code na sa dulo ng kahulugan ng pag-andar ng lambda.

Konklusyon

Ang expression ng lambda ay isang hindi nagpapakilalang pagpapaandar. Ito ay nasa dalawang bahagi: klase at bagay. Ang kahulugan nito ay isang uri ng klase. Kapag ang expression ay tinawag, ang isang bagay ay nabuo mula sa kahulugan. Ang bagay na ito ay tinatawag na isang pagsasara. Ito ang pagsasara na gumagawa ng gawaing inaasahan na gawin ng lambda.

Para sa lambda expression upang makatanggap ng isang variable mula sa isang panlabas na saklaw ng pag-andar, kailangan nito ng isang walang laman na sugnay na makuha sa kanyang function body.