Summary
In C++, when I return a lambda from a function that's captured a variable local to that function, what specifically happens, and why? The compiler (g++) seems to allow it, but it gives me different results than I was expecting, so I'm not sure if this is technically safe/supported.
Details
In some languages (Swift, Lisp, etc.) you can capture local variables in a closure/lambda, and they stay valid and in scope as long as the closure is in scope (I've heard it called "lambda over let over lambda" in a Lisp context). For example, in Swift, the example code for what I'm trying to do is:
func counter(initial: Int) -> (() -> Int) {
var count = initial
return { count += 1; return count }
}
let c = counter(initial: 0)
c() // returns 1
c() // returns 2
c() // returns 3
I tried to write a C++ equivalent of this like the following:
auto counter(int initial)
{
int count = initial;
return [&count] () -> int {
count = count + 1;
return count;
};
}
However, the result I get is:
auto c = counter(0);
std::cout << c() << std::endl; // prints 1
std::cout << c() << std::endl; // prints 1
std::cout << c() << std::endl; // prints 1
If I capture a variable that's still in scope, it works as I'd expect. For example, if I do all of the following in a single function:
int count = 0;
auto c = [&count] () -> int {
count = count + 1;
return count;
};
std::cout << c() << std::endl; // prints 1
std::cout << c() << std::endl; // prints 2
std::cout << c() << std::endl; // prints 3
So I guess my question is, in the first C++ example above, what is actually getting captured? And is it defined behavior, or do I just have a reference to some random memory on the stack?
Aucun commentaire:
Enregistrer un commentaire