de-vraag
  • Klausimai
  • Žymos
  • Vartotojai
Pranešimai
Apdovanojimai
Registracija
Užsiregistravę gausite pranešimus apie atsakymus ir komentarus į savo klausimus.
Prisijungti
Jei jau turite paskyrą, prisijunkite ir patikrinkite naujus pranešimus.
Už pridėtus klausimus, atsakymus ir komentarus bus skiriami apdovanojimai.
Daugiau
Šaltinis
Redaguoti
 Nawaz
Nawaz
Question

Kas yra lambda išraiška C++11?

Kas yra lambda išraiška C++11? Kada galėčiau ją naudoti? Kokios klasės problemą jos išsprendžia, kurios nebuvo įmanoma išspręsti iki jų įvedimo?

Būtų naudinga pateikti keletą pavyzdžių ir panaudojimo atvejų.

1398 2011-10-02T14:58:12+00:00 3
 hugomg
hugomg
Redaguotas klausimas popietr lapkritis 2011 в 9:12
Programavimas
c++
lambda
c++-faq
c++11
Popular videos
C++ LAMBDA SYNTAX | C++ 11/14 FEATURES| BENEFITS OF USING LAMBDA  FUNCTION| C/C++ Lectures
C++ LAMBDA SYNTAX | C++ 11/14 FEATURES| BENEFITS OF USING LAMBDA FUNCTION| C/C++ Lectures
prieš 2 metus
Lambdas in C++
Lambdas in C++
prieš 4 metus
C++ 11 Lambda Functions
C++ 11 Lambda Functions
prieš 6 metus
Programavimas C++ 11 #4 - Pirmosios programos apžvalga
Programavimas C++ 11 #4 - Pirmosios programos apžvalga
prieš 5 metus
Programavimas visiškai žaliems: Ciklai
Programavimas visiškai žaliems: Ciklai
prieš 2 metus
Programavimo kalba Java #8 Lamda išraiškos funkcinis interfeisas
Programavimo kalba Java #8 Lamda išraiškos funkcinis interfeisas
prieš 2 metus
#4 Lambda expressions in Programming Java
#4 Lambda expressions in Programming Java
prieš 1 metus
Proof by induction | Sequences, series and induction | Precalculus | Khan Academy
Proof by induction | Sequences, series and induction | Precalculus | Khan Academy
prieš 10 metų
#9 Proof by induction sigma 9^n-2^n is divisible by 7 How to use mathgotserved
#9 Proof by induction sigma 9^n-2^n is divisible by 7 How to use mathgotserved
prieš 7 metus
Pirma pamoka (programavimas internete c++ )
Pirma pamoka (programavimas internete c++ )
prieš 2 metus
Proof by Induction - Example 1
Proof by Induction - Example 1
prieš 11 metų
MATHEMATICAL INDUCTION - DISCRETE MATHEMATICS
MATHEMATICAL INDUCTION - DISCRETE MATHEMATICS
prieš 7 metus
How to Download and Install Turbo C/C++ on Windows 10
How to Download and Install Turbo C/C++ on Windows 10
prieš 6 metus
Induction: Divisibility Proof example 1 (n³ + 3n² + 2n is divisible by 6)
Induction: Divisibility Proof example 1 (n³ + 3n² + 2n is divisible by 6)
prieš 9 metus
#1 Mobiliosios programėlės PI18C
#1 Mobiliosios programėlės PI18C
prieš 1 metus
When not knowing Math can cost you $15,000
When not knowing Math can cost you $15,000
prieš 14 metų
How to learn any language in six months | Chris Lonsdale | TEDxLingnanUniversity
How to learn any language in six months | Chris Lonsdale | TEDxLingnanUniversity
prieš 8 metus
Proof by Mathematical Induction - How to do a Mathematical Induction Proof ( Example 1 )
Proof by Mathematical Induction - How to do a Mathematical Induction Proof ( Example 1 )
prieš 9 metus
« Ankstesnis
Kitas »
Šis klausimas turi 1 atsakymas atsakymų anglų kalba, norėdami juos perskaityti prisijunkite prie savo paskyros.
Solution / Answer
 Flexo
Flexo
popietr spalis 2011 в 3:21
2011-10-02T15:21:05+00:00
Daugiau
Šaltinis
Redaguoti
#13511422

Problema

C++ turi naudingų bendrųjų funkcijų, tokių kaip std::for_each ir std::transform, kurios gali būti labai patogios. Deja, jomis naudotis taip pat gali būti gana sudėtinga, ypač jei funktorius, kurį norite taikyti, yra unikalus konkrečiai funkcijai.

#include <algorithm>
#include <vector>

namespace {
  struct f {
    void operator()(int) {
      // do something
    }
  };
}

void func(std::vector<int>& v) {
  f f;
  std::for_each(v.begin(), v.end(), f);
}

Jei f naudojate tik vieną kartą ir tik toje konkrečioje vietoje, atrodo, kad rašyti visą klasę vien tam, kad atliktumėte kažką trivialaus ir vienkartinio, yra perteklinis dalykas.

C++03 gali kilti pagunda parašyti kažką panašaus į tai, kas išdėstyta toliau, kad funktorius išliktų vietinis:

void func2(std::vector<int>& v) {
  struct {
    void operator()(int) {
       // do something
    }
  } f;
  std::for_each(v.begin(), v.end(), f);
}

tačiau tai neleistina, nes C++03 sistemoje f negalima perduoti šablono funkcijai.

Naujas sprendimas

C++11 įvestos lambdos leidžia parašyti į eilutę įvestą anoniminį funktorių, kuris pakeistų struktą f. Nedideliuose paprastuose pavyzdžiuose tai gali būti švariau skaitoma (viskas laikoma vienoje vietoje) ir potencialiai paprasčiau prižiūrėti, pvz:

void func3(std::vector<int>& v) {
  std::for_each(v.begin(), v.end(), [](int) { /* do something here*/ });
}

Lambda funkcijos - tai tik sintaksinis cukrus anoniminiams funktoriams.

Grąžinimo tipai

Paprastais atvejais lambda funkcijos grąžinimo tipas išvedamas už jus, pvz:

void func4(std::vector<double>& v) {
  std::transform(v.begin(), v.end(), v.begin(),
                 [](double d) { return d < 0.00001 ? 0 : d; }
                 );
}

tačiau kai pradėsite rašyti sudėtingesnes lambdas, greitai susidursite su atvejais, kai kompiliatorius negali išvesti grąžinimo tipo, pvz:

void func4(std::vector<double>& v) {
    std::transform(v.begin(), v.end(), v.begin(),
        [](double d) {
            if (d < 0.0001) {
                return 0;
            } else {
                return d;
            }
        });
}

Kad tai išspręstumėte, galite aiškiai nurodyti lambda funkcijos grąžinimo tipą, naudodami -> T:

void func4(std::vector<double>& v) {
    std::transform(v.begin(), v.end(), v.begin(),
        [](double d) -> double {
            if (d < 0.0001) {
                return 0;
            } else {
                return d;
            }
        });
}

Kintamųjų "fiksavimas"

Iki šiol nenaudojome nieko kito, išskyrus tai, kas buvo perduota lambda, tačiau lambda viduje galime naudoti ir kitus kintamuosius. Jei norite gauti prieigą prie kitų kintamųjų, galite naudoti užfiksavimo sąlygą (išraiškos []), kuri kol kas šiuose pavyzdžiuose buvo nenaudojama, pvz:

void func5(std::vector<double>& v, const double& epsilon) {
    std::transform(v.begin(), v.end(), v.begin(),
        [epsilon](double d) -> double {
            if (d < epsilon) {
                return 0;
            } else {
                return d;
            }
        });
}

Galite užfiksuoti ir pagal nuorodą, ir pagal vertę, kurias galite nurodyti atitinkamai naudodami & ir =:

  • [&epsilon] užfiksuoti pagal nuorodą
  • [&] visus lambda sistemoje naudojamus kintamuosius fiksuoja pagal nuorodą
  • [=] fiksuoja visus lambda sistemoje naudojamus kintamuosius pagal vertę
  • [&, epsilon] fiksuoja kintamuosius kaip ir su [&], bet epsilon pagal vertę
  • [=, &epsilon] perima kintamuosius kaip ir su [=], bet epsilon pagal nuorodą

Pagal numatytuosius nustatymus sukurtas operatorius() yra const, o tai reiškia, kad pagal numatytuosius nustatymus, kai prie jų prieisite, captures bus const. Tai lemia, kad kiekvienas skambutis su ta pačia įvestimi duos tą patį rezultatą, tačiau galite pažymėti lambda kaip mutable, norėdami paprašyti, kad sukurtas operatorius() nebūtų const.

 AAEM
AAEM
Redaguotas atsakymas priešpietr rugpjūtis 2018 в 9:50
Function template - cppreference.com
en.cppreference.com
1418
0
 pmr
pmr
popietr spalis 2011 в 3:43
2011-10-02T15:43:48+00:00
Daugiau
Šaltinis
Redaguoti
#13511423

Kas yra lambda funkcija?

C++ lambda funkcijos sąvoka kilo iš lambda skaičiuoklės ir funkcinio programavimo. Lambda - tai neįvardyta funkcija, kuri naudinga (faktiniame programavime, o ne teorijoje) trumpoms kodo atkarpoms, kurių neįmanoma pakartotinai panaudoti ir kurių neverta įvardyti.

C++ kalboje lambda funkcija apibrėžiama taip

[]() { } // barebone lambda

arba visa jos šlovė

[]() mutable -> T { } // T is the return type, still lacking throw()

[] yra užfiksavimo sąrašas, () - argumentų sąrašas, o {} - funkcijos kūnas.

Gaudymo sąrašas

Užfiksavimo sąrašas apibrėžia, kas ir kaip iš lambda išorinės pusės turėtų būti prieinama funkcijos kūno viduje. Jis gali būti:

  1. reikšmė: [x]
  2. nuoroda [&x]
  3. bet kuris šiuo metu apimamoje srityje esantis kintamasis pagal nuorodą [&]
  4. tas pats kaip 3, bet pagal vertę [=]

Bet kurį iš pirmiau išvardytų variantų galite sujungti į kableliais atskirtą sąrašą [x, &y].

Argumentų sąrašas

Argumentų sąrašas yra toks pat, kaip ir bet kurioje kitoje C++ funkcijoje.

Funkcijos kūnas

Kodas, kuris bus vykdomas, kai lambda bus iš tikrųjų iškviesta.

Grąžinimo tipo išskaičiavimas

Jei lambda turi tik vieną grąžinimo teiginį, grąžinimo tipas gali būti praleistas ir turi numanomą tipą decltype(return_statement).

Mutable

Jei lambda pažymėta kaip mutable (pvz., []() mutable { }), leidžiama mutuoti reikšmes, kurios buvo užfiksuotos value.

Naudojimo atvejai

ISO standarte apibrėžtai bibliotekai lambda duoda daug naudos ir keleriopai padidina naudojimo patogumą, nes dabar naudotojams nereikia užgriozdinti kodo mažais funktoriais tam tikroje prieinamoje srityje.

C++14

C++14 lambdos buvo išplėstos įvairiais pasiūlymais.

Inicijuotos lambda užrašai

Dabar gaudymo sąrašo elementą galima inicializuoti su =. Tai leidžia pervadinti kintamuosius ir užfiksuoti juos perkeliant. Pavyzdys paimtas iš standarto:

int x = 4;
auto y = [&r = x, x = x+1]()->int {
            r += 2;
            return x+2;
         }();  // Updates ::x to 6, and initializes y to 7.

ir iš Vikipedijos paimtas pavyzdys, rodantis, kaip perimti kintamuosius naudojant std::move:

auto ptr = std::make_unique<int>(10); // See below for std::make_unique
auto lambda = [ptr = std::move(ptr)] {return *ptr;};

Bendrosios lambdos

Dabar lambdos gali būti bendrinės (auto čia būtų lygiavertis T, jei T būtų tipo šablono argumentas kur nors aplinkinėje srityje):

auto lambda = [](auto x, auto y) {return x + y;};

Patobulintas grąžinimo tipo išskaičiavimas

C++14 leidžia išvesti grąžinimo tipus kiekvienai funkcijai ir neapsiriboja tik funkcijomis, turinčiomis formą grąžinti išraišką;. Tai taip pat taikoma ir lambdoms.

 pmr
pmr
Redaguotas atsakymas priešpietr birželis 2014 в 9:26
799
0
 nobar
nobar
priešpietr kovas 2013 в 8:08
2013-03-01T08:08:08+00:00
Daugiau
Šaltinis
Redaguoti
#13511424

Lambda išraiškos paprastai naudojamos algoritmams užsklęsti, kad juos būtų galima perduoti kitai funkcijai. Tačiau galima lambda išraišką įvykdyti iš karto ją apibrėžus:

[&](){ ...your code... }(); // immediately executed lambda expression

funkciniu požiūriu yra lygiavertis

{ ...your code... } // simple code block

Dėl to lambda išraiškos yra galingas sudėtingų funkcijų pertvarkymo įrankis. Pradėkite nuo to, kad kodo sekciją įvilksite į lambda funkciją, kaip parodyta pirmiau. Tuomet aiškaus parametrizavimo procesą galima atlikti palaipsniui, po kiekvieno žingsnio atliekant tarpinį testavimą. Kai kodo blokas bus visiškai parametrizuotas (tai rodo & pašalinimas), galite perkelti kodą į išorinę vietą ir paversti jį įprasta funkcija.

Panašiai galite naudoti lambda išraiškas, norėdami inicializuoti kintamuosius pagal algoritmo rezultatą...

int a = []( int b ){ int r=1; while (b>0) r*=b--; return r; }(5); // 5!

Kaip būdas suskirstyti programos logiką, jums gali būti naudinga netgi perduoti lambda išraišką kaip argumentą kitai lambda išraiškai...

[&]( std::function<void()> algorithm ) // wrapper section
   {
   ...your wrapper code...
   algorithm();
   ...your wrapper code...
   }
([&]() // algorithm section
   {
   ...your algorithm code...
   });

Lambda išraiškos taip pat leidžia kurti pavadintas įterptines funkcijas, o tai gali būti patogus būdas išvengti logikos dubliavimo. Be to, naudojant įvardytas lambdas paprastai būna šiek tiek paprasčiau (palyginti su anoniminėmis inline lambdomis), kai kitai funkcijai kaip parametras perduodama netriviali funkcija. Pastaba: nepamirškite kabliataškio po uždaromojo lenktinio skliausto.

auto algorithm = [&]( double x, double m, double b ) -> double
   {
   return m*x+b;
   };

int a=algorithm(1,2,3), b=algorithm(4,5,6);

Jei vėlesnis profiliavimas atskleis dideles funkcijos objekto inicializavimo pridėtines išlaidas, galite nuspręsti tai perrašyti kaip įprastą funkciją.

 NightFurry
NightFurry
Redaguotas atsakymas priešpietr lapkritis 2015 в 9:22
Nested function - Wikipedia
en.wikipedia.org
165
0
Pridėti klausimą
Kategorijos
Visi
Technologijos
Kultūra / poilsis
Gyvenimas / Menai
Mokslas
Profesionalus
Verslas
Vartotojai
Visi
Naujas
Populiarus
1
mohidil qodirova
Registruota prieš 2 dienas
2
Jasur Fozilov
Registruota prieš 2 dienas
3
Zuxriddin Muydinov
Registruota prieš 3 dienas
4
Денис Анненский
Registruota prieš 5 dienas
5
365
Registruota prieš 1 savaitę
BG
DE
EL
ES
FR
ID
IT
JA
KO
LT
NL
PT
RU
TR
ZH
© de-vraag 2022
Šaltinis
stackoverflow.com
pagal licenciją cc by-sa 3.0 nurodant autorystę