Reputation: 11
I am learning c++11 new function lambda function and am a little confused. I read that
[] 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
My question is what exactly does capture a variable mean and what's the difference with return a value, if you want to capture a variable you have to return it right?
For example:
[] () { int a = 2; return a; }
Why is it not
int [] () { int a = 2; return a; }
Upvotes: 0
Views: 3388
Reputation: 24249
One of the key features of a lambda function is that it can remember things from the scope in which it was declared:
#include <iostream>
#include <vector>
#include <functional>
auto f(int i, int j) {
int k = i * j;
return [=](){ std::cout << k << "\n"; };
}
int main() {
std::vector<std::function<void(void)>> v;
v.push_back(f(2,2));
v.push_back(f(6, 7));
for (auto& l: v) {
l();
}
}
Note how we don't have to pass anything to the lambda when we call it?
Lambdas are essentially syntactic sugar around functor objects, and capture is the process of adding member variables to the functor:
[](char* p){ *p = toupper(*p); }
struct Lambda1 {
int operator(char* p) const { *p = toupper(*p); }
};
int x = 42;
int y = 5;
[x, &y](int i){ return i * (x + y); }
struct Lambda2 {
int x_;
int& y_;
Lambda2(int x, int& y) : x_(x), y_(y) {}
int operator(int i) { return i*(x_ + y_); }
};
Returning a value from a lambda is optional, but the return value is the output of the lambda, not the input.
Upvotes: 2
Reputation: 2369
The capture list is for bringing symbols into the lambda. A return value is for, well, returning a value out of a lambda.
Also, lambdas use the trailing return type syntax, like this [] () -> int { int a=2; return a; }
. Though often it's better to leave it implicitely deduced
Upvotes: 2
Reputation: 72271
You can "capture" variables that belong to the enclosing function.
void f() {
int a=1;
// This lambda is constructed with a copy of a, at value 1.
auto l1 = [a] { return a; };
// This lambda contains a reference to a, so its a is the same as f's.
auto l2 = [&a] { return a; };
a = 2;
std::cout << l1() << "\n"; // prints 1
std::cout << l2() << "\n"; // prints 2
}
You can return a captured variable if you want, or you can return something else. The return value is unrelated to captures.
Upvotes: 4