2016-09-01 5 views
3

C++ 11でラムダを覚えた後、私はこれを書いて、出力に混乱しました。この場合のラムダ出力との混乱

auto f1 = []() { 
    int tmp = 10; 
    int *tmp_p = &tmp; 
    return [tmp_p] (int x) { 
     return *tmp_p + x; 
    }; 
}(); 

auto f2 = []() { 
    int tmp = 10; 
    return [&tmp] (int x) { 
     return tmp + x; 
    }; 
}(); 

cout << f1(5) << endl; 
cout << f1(5) << endl; 

cout << f2(5) << endl; 
cout << f2(5) << endl; 

出力は次のとおりです。

15 
5772973 
2686617 
2686617 

この背後にある理由は何ですか?

+3

しかし、パラメータ付きのラムダを返してすぐに実行されます。 –

+0

@AdrianJałoszewskiごめんなさい –

答えて

7

未定義の動作です。

tmpは、f1が割り当てられた後に破壊されるため、tmp_pはダングリングポインタになります。あなたが逆参照したときに何かが起こることがあります。時には適切な値の15が与えられ、時には5772973も含まれます。

f2でも同じですが、ポインタを使用する代わりに、破壊されたオブジェクトを参照する参照を使用します。これは未定義の動作です。

5

これは私たちがundefined behaviorと呼ぶものです。あなたのコードが未定義の動作を引き起こすのはなぜですか?

最初のケース:f1(): これらのラムダを呼び出した後int tmpint *tmp_pの値はもうスタック上にないので、それは(int *tmp_pがコピーされたが、int tmpを除去した)、それを引き起こしています。

第2のケース:f2()tmpの値は、内側のラムダを参照することによってアクセスされました。ラムダの生成が終了した後、それはスタックにもうなくなり、何かがメモリを取得してゴミを書き込んだ。

関連する問題