In the code below, I create a lambda that captures a local variable by reference. Note that this is a pointer, so if C ++ lambdas are true closures, it must survive the lifetime of the function that the lambda creates.
However, when I call it again, instead of creating a new local variable (new environment), it repeats the same as before, and actually captures exactly the same pointer as before.
This seems wrong. Either C ++ lambdas are not true closures, or is my code incorrect?
Thanks for any help
#include <iostream> #include <functional> #include <memory> std::function<int()> create_counter() { std::shared_ptr<int> counter = std::make_shared<int>(0); auto f = [&] () -> int { return ++(*counter); }; return f; } int main() { auto counter1 = create_counter(); auto counter2 = create_counter(); std::cout << counter1() << std::endl; std::cout << counter1() << std::endl; std::cout << counter2() << std::endl; std::cout << counter2() << std::endl; std::cout << counter1() << std::endl; return 0; }
This code returns:
1 2 3 4 5
But I expected him to return:
1 2 1 2 3
Further editing :
Thanks for pointing out the error in my source code. Now I see that what happens is that the pointer is deleted after calling create_couter, and the new create simply reuses the same memory address.
Which brings me to my true question, then I want to do the following:
std::function<int()> create_counter() { int counter = 0; auto f = [&] () -> int { return ++counter; }; return f; }
If C ++ lambdas were true closures, each local counter will coexist with the returned function (the function carries its own environment - at least part of it). Instead, the counter is destroyed after a call to create_counter, and a call to the returned function generates a segmentation error. This is not the expected closure behavior.
Marco A offered a job: make the pointer a passed copy. This increases the control counter, so it does not break after create_counter. But it is kludge. But, as Marco noted, he works and does exactly what I expected.
Jarod42 suggests declaring a variable and initializing it as part of a capture list. But this defeats the goal of closure, since the variables are then local to the function, not the environment in which the function is created.
apple apple suggests using a static counter. But this is a workaround to avoid deleting the variable at the end of the create_function, which means that all the returned functions have the same variable, and not the environment in which they are executed.
So, I think the conclusion (if someone cannot shed more light) is that lambdas in C ++ are not true closures.
Thanks again for your comments.