Reputation: 279
Here is my code,I want to test closure in c++ like javascript. Why the compiler yield this message? "testLambda.cpp: In lambda function: testLambda.cpp:8:11: error: ‘a’ is not captured"
#include <iostream>
#include <functional>
std::function<bool(int)> returnLambda(int a){
auto b = 1;
auto c = 2;
return [&](int x)
{ return x*(b++)+c+a == 0;};
}
auto f = returnLambda(21);
int main(){
auto c = f(1);
auto b = f(1);
std::cout<<c<<b<<std::endl;
return 0;
}
Upvotes: 2
Views: 4957
Reputation: 27460
Benjamin Lindley provided an answer about declaration of lambdas in C++.
But technically speaking you cannot reproduce JavaScript closures using C++ lambdas.
In JS outer variables that used by local function are protected by GC mechanism.
But in C++, if you capture variables by reference, you can easily get into situation when referenced variables are destroyed and you'll get segmentation fault / access violation.
This, for example:
#include <iostream>
#include <functional>
std::function<bool(int)> returnLambda(int a){
auto b = 1;
auto c = 2;
return [&](int x)
{ return x*(b++)+c == 0;};
}
auto f = returnLambda(21);
int main(){
auto c = f(1);
auto b = f(1);
std::cout<<c<<b<<std::endl;
return 0;
}
will crash badly as after return from the returnLambda() its variables a,b and c are destroyed (their stack location is used by something else) when function f() is called.
Upvotes: 2
Reputation: 103693
You need to specify your captures in the square brackets, that's why lambdas require square brackets in the first place. You can capture them by reference:
[&a,&b,&c] (int x) ...
or by value:
[a,b,c] (int x) ...
or mix it up:
[a,&b,c] (int x) ...
Or you can just capture everything that you use:
[&] (int x) ... // by reference
[=] (int x) ... // by value
If you choose to capture a variable by value, but need to modify it, then you need to make it mutable:
[=] (int x) mutable ...
Upvotes: 11