There is an error in your code because it contains a broken link; reference c will refer to a local variable in the outer lambda that will be destroyed when the outer lambda returns.
You must write it using mutable lambda bypass capture:
auto a = []() { int c = 0; return [=]() mutable { cout << c++; }; };
It depends on a post-standard extension allowing multiple operators to be used in lambda with a return type; Is there a reason lambdas does not allow the return of a return type if it contains more than one statement? The easiest way to fix this is to specify a parameter so that the lambda contains only one statement:
auto a = [](int c) { return [=]() mutable { cout << c++; }; };
Unfortunately, the default options are not allowed in lambdas, so you should call this as a(0) . Alternatively, due to readability, you can use the nested lambda call:
auto a = []() { return ([](int c) { return [=]() mutable { cout << c++; }; })(0); };
How it works, when a executes an internal lambda it copies all the reference variables into an instance of its closure type, which will be something like this:
struct inner_lambda { int c; void operator()() { cout << c++; } };
Then the instance of the closure type is returned by the external lambda and can be called and will change its copy c when called.
In general, your (fixed) code translates to:
struct outer_lambda { // no closure struct inner_lambda { int c; // by-value capture // non-const because "mutable" void operator()() { cout << c++; } } // const because non-"mutable" inner_lambda operator()(int c) const { return inner_lambda{c}; } };
If you left c as a capture by reference, it would be:
struct outer_lambda {
Here inner_lambda::c is a dangling reference to a local parameter variable c .
ecatmur Sep 28 '12 at 12:14 2012-09-28 12:14
source share