2016-05-03 16 views
0

私はCppCon 2015のビデオを見ています。C++ラムダ:良いリファレンスと悪いリファレンス

Enter image description here

アーサーは説明したが、私はそれを得ることはありません...アーサーは悪い参照は、終了し、ローカル変数を参照しているが、スタックを出た後にクリーンアップするものとローカル変数がなくなっていると言いますだから問題は何ですか?

+1

知っていますか){int型のx = 5; return x;} '? – immibis

+0

問題はまさにあなたが言ったことです - あなたは何かを参照しているものを返しています。そんなことで何ができますか? –

答えて

3

@ Barryの回答が別の言い方で言ったことを説明したいと思います。

BAD_increment_byの中に起こったことを書き留めましょう。

  1. ローカル変数yがあります。
  2. ラムダキャプチャy参照。これによりyという参照が作成されます。さて、彼らは同じ名前を持っている、それは混乱している...最初の1つを "値y"と呼び、2番目のものを "y"と呼びましょう。
  3. ラムダ本体には参照番号yが使用されています。
  4. ラムダはBAD_increment_byによって返されます。 BAD_increment_byから戻った後

  1. yは存在しません。
  2. リファレンスyはまだy ...
  3. 待ちを評価するために指しています!値yが存在しません!参照yは何かが存在しないことを指しています!誰かがラムダを呼び出す

  1. 参考y読み込まれます。
  2. 参照番号yは参照番号であるため、値yにリダイレクトされます。
  3. Errr ...それは本当に値yですか、それとも私の幻覚ですか?

結論は次のとおりです。ラムダが呼び出されると、ダングリングリファレンスが使用されます。この動作は未定義です。

+0

ありがとうございました!今私はそれを得た。 – athos

6

BAD_increment_byは、その中にyの参照を含むクロージャを返しますが、yは、その関数が返ったときに範囲外になるため、参照が含まれていません。そのクロージャを呼び出す試みは未定義の動作です。

それは同じ理由で悪い:

int& BAD_copy(int x) { return x; } 

が悪いです。

+0

あなたは "[&]"を書くことによって、返されるものはもはや*値7ではなく、値7のローカル無名変数の*参照*であることを意味しますか? – athos

+0

@athos返されません。ラムダ自体はローカル変数 'y'を参照する' int& '型のメンバを持っています。 – Barry

+0

それから私はそれを取得しません。だから、BAD_increment_byの例は、int型のメンバを持っています。匿名ですので、ローカル変数yを参照するryを呼び出してみましょう。誰も使用していません。 – athos

1

ラムダは、operator()のクラスの省略形と考えることができるので、関数のように扱うことができます。

auto BAD_increment_by(int y) 
{ 
    return [&](int x){return x+y;}; 
} 

は次のために短い手考慮することができる:

struct BadClosure 
{ 
    int& y; 
    BadClosure(int& y) // y is the only variable in scope 
     : y(y)   // So the `&` only captures 'y' 
    {} 
    auto operator()(int x){return x+y;} 
}; 
auto BAD_increment_by(int y) 
{ 
    return BadClosure(y); 
} 

だから私は上記を使用する場合:あなたは `INT&F(と間違って何

int main() 
{ 
    // This object now has a reference to 
    // parameter 'y' from the function `BAD_increment_by()` 
    // 
    // But this function has exited. 
    // So the reference held by this object is no longer 
    // valid (ie it is a dangling reference). 
    auto addTwo = BAD_increment_by(2); 


    // Now use it 
    // Internally this access the member y 
    // which is a reference to the parameter 'y' 
    // from a function that is no longer executing. 
    std::cout << addTwo(5) << "\n"; 
} 
関連する問題