Your code has a bug in that it contains a dangling reference; the c
reference will refer to the local variable in the outer lambda, which will be destroyed when the outer lambda returns.
You should write it using a mutable
by-value lambda capture:
auto a = []() {
int c = 0;
return [=]() mutable {
cout << c++;
};
};
This relies on a post-standard extension to allow multiple statements in a return-type-deducing lambda; Is there a reason on not allowing lambdas to deduce the return type if it contains more than one statement? The easiest way to fix it is to supply a parameter so that the lambda contains only a single statement:
auto a = [](int c) {
return [=]() mutable {
cout << c++;
};
};
Unfortunately default parameters aren't allowed in lambdas, so you'd have to call this as a(0)
. Alternatively at the cost of readability you could use a nested lambda call:
auto a = []() {
return ([](int c) {
return [=]() mutable {
cout << c++;
};
})(0);
};
The way this works is that when a
executes the inner lambda copies all the referenced variables into an instance of its closure type, which here would be something like:
struct inner_lambda {
int c;
void operator()() { cout << c++; }
};
The instance of the closure type is then returned by the outer lambda, and can be invoked and will modify its copy of c
when called.
Overall, your (fixed) code is translated 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 by-reference capture, this would be:
struct outer_lambda {
// no closure
struct inner_lambda {
int &c; // by-reference capture
void operator()() const { cout << c++; } // const, but can modify c
}
inner_lambda operator()(int c) const {
return inner_lambda{c};
}
};
Here inner_lambda::c
is a dangling reference to the local parameter variable c
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…