I know C++ fairly well. I have used lambdas and closures in other languages. For my learning, I wanted to see what I could do with these in C++.
Fully knowing the "danger" and expecting the compiler to reject this, I created a lambda in a function using a function stack variable by reference and returned the lambda. The compiler allowed it and strange things occurred.
Why did the compiler allow this? Is this just a matter of the compiler not being able to detect that I did something very, very bad and the results are just "undefined behavior"? Is this a compiler issue? Does the spec have anything to say about this?
Tested on a recent mac, with MacPorts-installed gcc 4.7.1 and the -std=c++11 compile option.
Code used:
#include <functional>
#include <iostream>
using namespace std;
// This is the same as actsWicked() except for the commented out line
function<int (int)> actsStatic() {
int y = 0;
// cout << "y = " << y << " at creation" << endl;
auto f = [&y](int toAdd) {
y += toAdd;
return y;
};
return f;
}
function<int (int)> actsWicked() {
int y = 0;
cout << "actsWicked: y = " << y << " at creation" << endl;
auto f = [&y](int toAdd) {
y += toAdd;
return y;
};
return f;
}
void test(const function<int (int)>& f, const int arg, const int expected) {
const int result = f(arg);
cout << "arg: " << arg
<< " expected: " << expected << " "
<< (expected == result ? "=" : "!") << "= "
<< "result: " << result << endl;
}
int main(int argc, char **argv) {
auto s = actsStatic();
test(s, 1, 1);
test(s, 1, 2);
test(actsStatic(), 1, 1);
test(s, 1, 3);
auto w = actsWicked();
test(w, 1, 1);
test(w, 1, 2);
test(actsWicked(), 1, 1);
test(w, 1, 3);
return 0;
}
Results:
arg: 1 expected: 1 == result: 1
arg: 1 expected: 2 == result: 2
arg: 1 expected: 1 != result: 3
arg: 1 expected: 3 != result: 4
actsWicked: y = 0 at creation
arg: 1 expected: 1 == result: 1
arg: 1 expected: 2 == result: 2
actsWicked: y = 0 at creation
arg: 1 expected: 1 == result: 1
arg: 1 expected: 3 != result: 153207395