私はC++をかなりよく知っています。私は他の言語でラムダとクロージャを使用しました。私の学習では、C++でこれらを使用して何ができるかを確認したいと思いました。
「危険」を完全に理解し、コンパイラがこれを拒否することを期待して、参照によって関数スタック変数を使用して関数にラムダを作成し、ラムダを返しました。コンパイラはそれを許可し、奇妙なことが起こりました。
なぜコンパイラはこれを許可したのですか?これは、コンパイラが私が非常に、非常に悪いことをしたことを検出できず、結果が単に「未定義の動作」であるという問題ですか?これはコンパイラの問題ですか?スペックにはこれについて何か言いたいことがありますか?
MacPortsがインストールされたgcc4.7.1と-std=c ++ 11コンパイルオプションを使用して、最近のMacでテストされました。
使用したコード:
#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;
}
結果:
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