Reputation: 4307
Can somebody please show me examples of the following:
1) Lambda that captures x
by value. y
by reference. What do the rest default to, if unspecified?
2) Lambda that captures x
by value. y
by reference, all else by value.
3) Lambda that captures x
by value. y
by reference, all else by reference.
Also, is it allowed that 2 lambdas in the same scope have the same capture signature, such as both be []
, or both be [&x, =]
Thanks
Upvotes: 20
Views: 12211
Reputation: 314
To quote Bjarne from his C++11 FAQ:
The [&] is a "capture list" specifying that local names used will be passed by reference. We could have said that we wanted to "capture" only v, we could have said so: [&v]. Had we wanted to pass v by value, we could have said so: [=v]. Capture nothing is [], capture all by references is [&], and capture all by value is [=]. If an action is neither common nor simple, I recommend using a named function object or function.
Upvotes: 2
Reputation: 1827
1) [x, &y](){}
rest is not captured
2) [=, &y](){}
3) [&, x](){}
The capture-list is a comma-separated list of zero or more captures, optionally beginning with the capture-default. The only capture defaults are & (by reference) and = (by value). If a capture-default is used, no other captures may use the same capture type. Any capture may appear only once.
Also, is it allowed that 2 lambdas in the same scope have the same capture signature, such as both be [], or both be [&x, =]
Of course it is allowed. Every lambda will be distinct object and have its distinct type. If you capture variable by value in two lambdas, then every lambda will have its copy. If you capture variable by reference in two lambdas, then every lambda will have a reference to the same captured variable.
Upvotes: 23
Reputation: 303087
Can just write some examples:
int x = 7, y = 12, z = 24;
auto lambda1 = [x, &y]{
// can't do this...
// std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl;
std::cout << "x=" << x << ", y=" << y << std::endl;
};
auto lambda2 = [=, x, &y]{
std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl;
};
auto lambda3 = [&, x, &y]{
std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl;
};
++x, ++y, ++z;
lambda1();
lambda2();
lambda3();
Now, lambda1
here can't use z
. There is no "implicit" capture, since we don't have =
or &
specified and z
doesn't appear in the capture list, we cannot print z
there. So that's an error if we tried to use the line I have commented out.
The other two are fine and would print 7, 13, 24, and 7, 13, 25, respectively. Note that the =
and &
must come first. Also, given that we're capturing all by value/reference, one of the other captures is redundant, so we could've done:
auto lambda2 = [=, &y]{ ... };
auto lambda3 = [&, x]{ ... };
Upvotes: 10
Reputation: 1246
1)
[x,&y](){} // the rest is not captured, eg `z` is not defined in the scope
2)
[=,&y](){} // `=` is capture everything by value
3)
[&,x](){} // `&` is capture everything by reference
Upvotes: 2