#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
// Block 1
{
auto inc = []() { int i = 0; return [&]() { return i++; }; }();
std::vector<int> v(10, 10);
std::generate(v.begin(), v.end(), inc);
for (auto i : v) std::cout << i << std::endl;
}
// Block 2
{
auto inc = []() { int i = 0; return [&]() { return i++; }; };
std::vector<int> v(10, 10);
std::generate(v.begin(), v.end(), inc());
for (auto i : v) std::cout << i << std::endl;
}
}
I am not sure why these two blocks produce different results.
Block 1: 32767 ... 32776
Block 2: 0 ... 10
And for std::generate
the generator(inc
) is passed by value, so I believe it should be fine, right?
I am running OS X.
Thanks,
A closure is a kind of object that contains a pointer or reference of some kind to a function to be executed along with the an instance of the data needed by the function.
Although C was created two decades after Lisp, it nonetheless lacks support for closures.
In computer science, a closure is a function that has an environment of its own. In this environment, there is at least one bound variable (a name that has a value, such as a number). The closure's environment keeps the bound variables in memory between uses of the closure.
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function's scope from an inner function.
I am not sure why these two blocks produce different results.
Both are undefined behavior, so the question is moot. In either case, we have a lambda like:
auto f = []() { int i = 0; return [&]() { return i++; }; };
And f()
returns a lambda that has a dangling reference: i
is destroyed at the end of the call to f
. It's immaterial when that dangling reference happens - whether it happens long before the generate()
call or into the generate()
call.
If you want to make a generating counter with a lambda, the direct way is to make the lambda mutable and use init-capture:
auto inc = [i=0]() mutable { return i++; };
The mutable
is required because lambdas are const
by default, and we need to directly modify the member i
.
The above is C++14 (due to the generalized init-capture). We could make this work in C++11 by simply changing the nested-lambda structure from the inner lambda capturing by reference to capturing by value:
auto inc = []{ int i = 0; return [=]() mutable { return i++; }; }();
// ~~~ ~~~~~~~
That's... kind of obnoxious, but it works?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With