anonymous function (tsz. anonymous functions)
A lambda kifejezések lehetővé teszik, hogy egy függvényt inline (helyben) definiáljunk, gyakran helyi változókkal vagy paraméterekkel együtt, és átadjuk például algoritmusoknak vagy eseménykezelőknek. Ez nagyban javítja a kód tömörségét, olvashatóságát, és rugalmasságát.
std::sort
-ban vagy std::for_each
-ben).
A lambda kifejezés általános formája:
(parameters) -> return_type {
// függvény törzse
}
#include <iostream>
int main() {
auto osszeg = (int a, int b) {
return a + b;
};
std::cout << osszeg(5, 3) << std::endl; // 8
return 0;
}
Itt az osszeg
egy változó, amely egy lambda függvényt tárol. Ez a lambda két egész számot vár és visszaadja az összegüket.
capture
listaA lambda kifejezés egyik legfontosabb része a capture lista. Ez határozza meg, hogy a lambda milyen külső változókat használhat. A capture lista szögletes zárójelek között van: .
: az összes használt külső változót értékként fogja el.
: az összes használt külső változót referenciaként fogja el.
#include <iostream>
int main() {
int x = 10;
int y = 20;
auto lambda1 = () {
std::cout << "x + y = " << x + y << std::endl;
};
lambda1(); // 30
auto lambda2 = () {
x += 5;
y += 10;
std::cout << "Modified: x = " << x << ", y = " << y << std::endl;
};
lambda2(); // Modified: x = 15, y = 30
std::cout << "Outside: x = " << x << ", y = " << y << std::endl;
// Outside: x = 15, y = 30
return 0;
}
Ha a return típus nem egyértelmű vagy összetettebb, megadhatjuk explicit módon:
auto f = (int a, int b) -> double {
return (double)(a + b) / 2;
};
A lambda kifejezéseket gyakran használjuk STL algoritmusoknál, például a std::sort
-nál vagy std::for_each
-nél.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> szamok = {5, 3, 9, 1, 7};
// Rendezés csökkenő sorrendbe lambda segítségével
std::sort(szamok.begin(), szamok.end(), (int a, int b) {
return a > b;
});
for (auto szam : szamok) {
std::cout << szam << " ";
}
std::cout << std::endl;
return 0;
}
A lambda kifejezéseket változókba menthetjük az auto
kulcsszóval:
auto f = (int x) { return x * x; };
std::cout << f(4); // 16
Alapból, ha egy lambda érték szerint capture-öl egy változót, akkor a lambda nem módosíthatja a captured változó másolatát, mert a lambda operator()
-ja const
.
Ha szeretnénk, hogy a lambda módosíthassa a captured változók másolatát, akkor használjuk a mutable
kulcsszót:
int x = 5;
auto f = () mutable {
x += 10;
std::cout << x << std::endl; // 15
};
f();
std::cout << x << std::endl; // 5, mert eredeti x nem változott
Nem minden lambda kell, hogy visszatérjen értéket. Lehetnek void típusúak is:
auto kiir = (const std::string& nev) {
std::cout << "Szia, " << nev << "!" << std::endl;
};
kiir("Dani");
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> szamok = {1, 5, 8, 3, 7, 10};
int hatar = 5;
int szamlalo = std::count_if(szamok.begin(), szamok.end(), (int x) {
return x > hatar;
});
std::cout << "Nagyobbak, mint " << hatar << ": " << szamlalo << std::endl;
return 0;
}
std::function
)Ha szükség van arra, hogy egy lambda változóként vagy paraméterként olyan függvényt tartalmazzon, aminek a típusa nem ismert (például bonyolult capture lista miatt), használhatjuk a std::function
típust:
#include <functional>
std::function<int(int,int)> osszeg = (int a, int b) {
return a + b;
};
Ez viszont kicsit lassabb, mert a std::function
egy absztrakt tároló.
Korábban, a C++11 előtt, az ilyen inline, név nélküli függvények megoldására gyakran használtak:
Példa funktorra:
struct Osszeg {
int operator()(int a, int b) {
return a + b;
}
};
Osszeg osszeg;
std::cout << osszeg(3, 4);
(parameters) -> return_type { body }
.mutable
kulcsszóval módosíthatjuk a capture-ölt változók másolatát.std::function
-nel tárolhatjuk lambda típusú változókat, ha szükséges.