lambda capture by value
Főnév
lambda capture by value (tsz. lambda capture by values)
- (informatika) A lambda függvények (lambda expressions) a C++ egyik modern és erőteljes eszközei. Lehetővé teszik, hogy névtelen függvényeket definiáljunk közvetlenül ott, ahol szükség van rájuk – például egy algoritmusban, egy callback-ben vagy egy másik függvény paramétereként.
Egy lambda formális szintaxisa:
[capture](parameter_list) -> return_type { body }
Ebben a szintaxisban a capture rész az ún. capture list vagy befogási lista. Ez határozza meg, hogy a lambda milyen külső változókat (amelyek a lambda definíciós helyén léteznek) “visz magával” a belsejébe, és hogyan.
Két alapvető mód van erre:
- érték szerint (
by value) → másolatot készít - referencia szerint (
by reference) → hivatkozást visz magával
Most az érték szerinti befogást fogjuk részletesen vizsgálni.
1️⃣ Mi az a capture by value?
Amikor érték szerint fogsz be egy változót, akkor a lambda másolatot készít az aktuális értékéről abban a pillanatban, amikor a lambdát létrehozod.
Ez azt jelenti, hogy:
- a lambda belsejében a változó egy saját példányon fog élni
- a lambda belsejében az eredeti változó további módosításai nem fognak látszani
- a lambda belsejében a befogott érték nem írható át (alapértelmezetten
constlesz)
Szintaxis:
[x] // csak az 'x' változót fogjuk be érték szerint
[=] // minden külső változót érték szerint fogunk be
2️⃣ Példa: egyszerű capture by value
#include <iostream>
int main() {
int x = 10;
auto lambda = [x]() {
std::cout << "x inside lambda: " << x << std::endl;
};
x = 20;
lambda(); // Mi lesz az eredmény?
}
Kimenet:
x inside lambda: 10
Magyarázat:
- A
[x]azt jelenti, hogy a lambda 10-es értékkel másolta be azx-et, amikor a lambdát létrehoztuk. - A későbbi
x = 20;módosítás a lambdán belül nem fog látszani, mert az a lambda példányába másolatként bekerültx-re nincs hatással.
3️⃣ Globális capture by value
A [=] szintaxis azt jelenti, hogy minden használt külső változót érték szerint fogunk be:
#include <iostream>
int main() {
int x = 5;
int y = 8;
auto lambda = [=]() {
std::cout << "x: " << x << ", y: " << y << std::endl;
};
x = 100;
y = 200;
lambda();
}
Kimenet:
x: 5, y: 8
Miért? A lambda létrehozásakor x és y aktuális értékei kerültek másolatként a lambda példányába. A későbbi módosítás nem látszik.
4️⃣ Miért hasznos az érték szerinti befogás?
- Biztonságos → nem kell aggódni, hogy a lambda élettartama alatt a külső változó időközben módosul.
- Egyszerű → másolat készül, ezért a lambda saját példányban “tárolja” az adatot.
- Thread-safe → ha a lambda egy másik szálban fut, a befogott érték stabil marad.
5️⃣ Módosíthatjuk-e a capture by value változót a lambdán belül?
Alapértelmezetten nem – mert a lambda belsejében a befogott érték const lesz.
Példa:
#include <iostream>
int main() {
int x = 5;
auto lambda = [x]() {
x = 10; // HIBA! x const
};
lambda();
}
Fordítási hiba: x const.
6️⃣ mutable kulcsszó használata
Ha azt szeretnéd, hogy a lambda belsejében az érték szerinti befogott változó módosítható legyen, használhatod a mutable kulcsszót:
#include <iostream>
int main() {
int x = 5;
auto lambda = [x]() mutable {
x = 10;
std::cout << "x in lambda: " << x << std::endl;
};
lambda();
std::cout << "x outside: " << x << std::endl;
}
Kimenet:
x in lambda: 10 x outside: 5
Mi történik?
- A lambda saját példányon másolatot készített
x-ről. - A
mutableengedélyezi, hogy ezt a másolatot a lambda belsejében módosítsuk. - Az eredeti
xa lambda kívül nem változott meg.
7️⃣ Capture by value → lifetime biztonság
Ha egy lokális változót akarsz befogni, capture by value védi meg a lambdát a dangling reference hibától.
Példa:
#include <iostream>
#include <functional>
std::function<void()> makeLambda() {
int x = 42;
return [x]() {
std::cout << "x: " << x << std::endl;
};
}
int main() {
auto lambda = makeLambda();
lambda(); // x még él, mert by value volt befogva!
}
Ha itt &x-el (referenciával) fogtuk volna be, a makeLambda() után x megszűnne → dangling reference.
8️⃣ Capture by value + move-only típusok
C++14-től kezdve capture listában lehet move-olni is változót:
auto ptr = std::make_unique<int>(42);
auto lambda = [p = std::move(ptr)]() {
std::cout << "p: " << *p << std::endl;
};
Itt p a lambda belsejébe move-olódik, így nem kell shared_ptr-t használnod, ha az ownership a lambdához kerül.
9️⃣ Összegzés
Capture by value előnyei:
✅ Stabil → nem változik, ha a külső változó módosul ✅ Biztonságos → nem lógó referencia ✅ Thread-safe → saját példány ✅ Egyszerű → [=] formában tömeges capture
Hátrányai:
⚠️ Másolási költség → ha nagy objektumot fogsz be, költséges lehet ⚠️ Alapértelmezésben nem módosítható (mutable kell hozzá)
10️⃣ Összefoglaló példa
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> v{1, 2, 3, 4, 5};
int factor = 2;
std::for_each(v.begin(), v.end(), [factor](int x) {
std::cout << x * factor << " ";
});
std::cout << std::endl;
}
Kimenet:
2 4 6 8 10
Itt factor érték szerint van befogva → biztosak lehetünk benne, hogy a for_each ciklus közben a factor értéke nem változik.
Záró gondolat
A capture by value a lambda egyik leghasznosabb eszköze:
- garantálja a stabil adatot
- megelőzi a hibás referenciákat
- egyszerű és intuitív
mutablesegítségével belső állapotkezelést is lehet vele csinálni.
Fontos figyelembe venni:
- mikor akarod fixálni a külső értéket →
by value - mikor akarsz frissített értéket látni →
by reference
- lambda capture by value - Szótár.net (en-hu)
- lambda capture by value - Sztaki (en-hu)
- lambda capture by value - Merriam–Webster
- lambda capture by value - Cambridge
- lambda capture by value - WordNet
- lambda capture by value - Яндекс (en-ru)
- lambda capture by value - Google (en-hu)
- lambda capture by value - Wikidata
- lambda capture by value - Wikipédia (angol)