2013-03-25 10 views
7

次のようなものがあるとします。ラムダ式が「これ」を卑劣に捕獲する

struct A 
{ 
    int x; 
    std::function<int()> f1() { return [=](){ return x; }; } 
    std::function<int()> f2() { return [=](){ return this->x; }; } 
    std::function<int()> f3() { return [this](){ return x; }; } 
    std::function<int()> f4() { return [this](){ return this->x; }; } 
    std::function<int()> f5() 
    { 
     int temp = x; 
     return [=](){ return temp; }; 
    } 
} 

次に、次のコードがあります。 f#f1, f2, f3, f4, f5のいずれかを参照している

auto a = std::make_shared<A>(); 
a->x = 5; 
std::function<int()> f = a.f#(); 
a.reset(); 
int x = f(); 

これらの関数は、2セットのいずれかで挙動を示すされています

  1. リターン5(f5)と呼ばれる、または
  2. は、間接参照nullptrf1, f2, f3, f4)しようとして墜落しました。

私はいくつかの暗黙的または明示的に、Aのメンバ関数で「this」をキャプチャしているためであると理解しています。

動作1または動作2を決定する正式なルールは何ですか。

は、私はそれがxをキャプチャするだろうと考え、f1に似た何かによって引き起こされたバグに対処しばらく過ごし、決してそれがthisをキャプチャするだろう考えると、私はこれは、文書を取得することが有用であると考えました。

答えて

8

この動作を決定する正式なルールはありません。この動作はが定義されていないため、です。

あなたのラムダが存在しないオブジェクトにアクセスしています。メンバー変数を値で直接取得することはできません。あなたは常にthisによってそれらをキャプチャします。これはあなたが参考にそれらをキャプチャしていることを意味します。オブジェクトが削除されると、その削除されたオブジェクトにアクセスしようとすると、未定義の動作が発生します。

例外はf5です。これは保証された一貫した値を返します。元のオブジェクトから完全に切り離されています。

+0

私はグループ 'f1、f2、f3、f4'と' f5'を後方にラベルしました!はい、私はそれが正しく動作するf5と、そうでないものとを意味しました。編集されました。 –