Can somebody please provide some insights on this? Is the lambda capturing external variables, or is the outside world capturing values produced by the lambdas? What does it mean for a certain variable to be captured?
The lambda is capturing an outside variable.
A lambda is a syntax for creating a class. Capturing a variable means that variable is passed to the constructor for that class.
A lambda can specify whether it's passed by reference or by value. For example:
[&] { x += 1; } // capture by reference
[=] { return x + 1; } // capture by value
The first produces a class roughly like this:
class foo {
int &x;
public:
foo(int &x) : x(x) {}
void operator()() const { x += 1; }
};
The second produces a class something like this:
class bar {
int x;
public:
bar(int x) : x(x) {}
int operator()() const { return x + 1; }
};
As with most uses of references, capturing by reference can create a dangling reference if the closure (the object of the class created by the lambda expression) out-lives the object that was captured.
[](){/* ... body ... */}
is convertible to a plain function pointer void(*)()
, so could be implemented as a free-standing function. Anyway, the compiler could do all sorts of trickery for capturing-lambdas. It could define functions that take pointers to local variables and dereference them for capture. It could simply append int x = /* captured value */
to the lambdas body in some cases. There are many ways it could be implemented other than a class with operator()()
. It's really up to the implementation. –
Lananna Jerry Coffin gave you detailed response,I agree that lambda is syntax for creating a class.There are bunch of options about the way variables are captured and how.List of options:
[] Capture nothing (or, a scorched earth strategy?)
[&] Capture any referenced variable by reference
[=] Capture any referenced variable by making a copy
[=, &foo] Capture any referenced variable by making a copy, but capture variable foo by reference
[bar] Capture bar by making a copy; don't copy anything else
[this] Capture the this pointer of the enclosing class
Lambda captures variables which it otherwise will not have access to. One can specify how A lambda should capture a variable .i.e value,reference . This has been explained really well here In lambda functions syntax, what purpose does a 'capture list' serve?
With capturing you can add variables to the "scope" of the lambda it usually would not have access to.
int x = 4;
auto divisibleByFour = [x] (int a){
return a % x;
};
if you would omit x
in the capture it would throw a compile error.
The lambda has access to x
due to the capture.
There are 4 forms of capture:
[=]
captures everything in the scope by value, i.e. it makes copies.
[&]
captures everything in the scope by reference.
[x,y]
capture the local variables x
and y
by value.
[&x,&y]
capture the local variables x
and y
by reference. changing x
and y
in the lambda are reflected outside the lambda.
you can also rename the capture:
[int& f = &x]
will make the lambda see f
instead of x
, but they mean the same variable.
Caution needs to be taken when storing the lambda:
std::function<int (x,y)> foo() {
int x = 3;
int y = 4;
return [&x,&y](){
return x + y;
}
// x and y are captured by reference and do not exist after the function returns
}
void doHorribleStuff() {
auto func = foo();
func();// invoke the lambda with non-existing captures!
}
© 2022 - 2024 — McMap. All rights reserved.