2017-10-09 14 views
2

次の例では、キャプチャリストで[&]というキャプチャを使用するのとは異なり、キャプチャリストで[this]を使用する方法の違いは何ですか?私は両方を試して、同じ出力を生成します。 C++プログラミング言語でラムダキャプチャリストの[this]と[&]は、クラス内で使用されていれば同等ですか?

#include <iostream>               

class Test {                 
public:                  
    int x = 2;                 
    void test1(void) { std::cout << "test1" << std::endl; };     

    void test_lambda(void) {             
     auto lambda = [&]() {            
      std::cout << "x: " << x << " y: " << y << " z: " << z << std::endl; 
      this->test1();               
     };                 

     lambda();                
    }                   

protected:                 
    int y = 3;                 

private:                  
    int z = 4;                 
};                   

int main() {                 
    Test t;                 
    t.test_lambda();               
} 

、Stroustropは言う:

Members are always captured by reference. That is, [this] implies that members are accessed through this rather than copied into the lambda. 

これは、彼らが同じことを意味するかもしれないことを示唆しているようです。しかし、それが事実なら、なぜ[これは]必要なのでしょうか?

+0

&特定の変数に使用することができます –

+2

常に使用できる最も強力でないキャプチャを使用してください。ローカルの推論をより簡単にするだけでなく、間違いを避けることもできます。 – KABoissonneault

答えて

2

[&]場合に参照により基準と現在のオブジェクトがラムダの本体で使用されるすべての自動変数は、[本]を使用して一方

存在する捕捉捕捉しますポインタはthisのみです。あなたがスコープで自動変数を持っているとき

これは、例えば、異なります:

struct Test { 
    void run() { 
    int y = 2; 

    // all automatic variables are accessible, both local and members 
    auto l1 = [&](){ cout << x << " " << y << endl; }; 
    l1(); 

    // y is not accessible, x is only because it's a member 
    auto l2 = [this]() { cout << this->x << endl; }; 
    l2(); 
    } 

    int x = 1; 
}; 

int main() { 
    Test t; 
    t.run(); 
} 

では、なぜ我々はそれが必要なのでしょうか?

[this]のキャプチャを許可することは、他のポインタのキャプチャを許可することと同じです。

すべての自動変数を常にキャプチャしないのはなぜですか?

  • カプセル化:理由のカップルには、があります時には、あなたはラムダが他の値
  • 柔軟性に精通している必要はありません:時々、私たちはいくつかの値をコピーする必要があり、参照することによりそれらのいくつかを渡す

注:はコンパイラが唯一トンを通過するので、追加のパフォーマンスコストを導入しない&を使用して、すべての自動変数のキャプチャ彼はラムダの内部で使用する変数です。

+0

Re: "performance"、cppreferenceの引用は、 。これはパフォーマンスに影響を与えません。それよりも小さくキャプチャすると、コンパイルは失敗するためです。 –

+0

@DanielH、ヒントありがとう、私はそれを逃した –

1

&は、参照によって範囲内にあるすべての変数をキャプチャします。

void test_lambda(void) {             
    int dummy = 42;     // capture dummy ?!? 
    auto lambda = [&]() {    // yes         
     std::cout << "x: " << x << " y: " << y << " z: " << z << std::endl; 
     this->test1(); 
     std::cout << dummy;   // ok here              
    };                 
    lambda();                
} 

[this]意志[&]としてローカル変数をキャプチャしません。これを考慮してください。 cppreferenceによれば

+0

質問は「[&] 'が[this]'よりも強力なので、なぜ[[this] 'が必要ですか?まったく? " –

+1

@RaymondChenあなたがキャプチャしたくないものをキャプチャしたくないからです。 – user463035818

+0

@RaymondChenこれは問題ではなく、質問は編集されていないことを考えれば、この引用をどこで取得していますか?私はそれが同じであるかどうか、どう違うかを尋ねるのと同じ方法でそれを読んだ。 –

1

メンバーをキャプチャするための唯一の方法は、thisをキャプチャすることにより、次のとおりです。参照することにより、キャプチャすることにより、暗黙的に

  • [=](){ member = 42;}によってキャプチャすることにより、暗黙的に明示

    • [this](){ member = 42; }
    • [&](){ member = 42; }

    は違法です

    • [&member](){ member = 42; } // illegal
    • [member](){ std::cout << member; } // illegal

  • はその後だけキャプチャします [this]を使用して

    +0

    私は標準をチェックしていないので、これはおそらくこれはコンパイラの拡張機能ですが、経験的に '[&member = member](){/*...*/ } 'うまく動作します。 –

    +0

    @DanielH:これは、変数によって初期化された* "named lambda member" *を宣言します。私はそれがメンバのキャプチャであるとは言いません(同じように 'auto&ref = member; [&ref](){/ * ...* /} '')、私にとっては初期化に過ぎません。 – Jarod42

    +0

    キャプチャと呼ばれ、この場合は同じ変数への参照です。キャプチャとリファレンスの初期化の間にどのような違いがあるのか​​よく分かりません。 2つの動作が異なる場合はありますか? –

    0

    ...(可能なダングリング参照を避けるために)referenceキャプチャを避け、あなたが明示的かどうかというの間で選択することがあります、キャプチャの制限を表現しようとするあなたに依存しますthisであり、[&]は、囲みスコープのすべてのローカル変数をキャプチャします。thisおよび

    struct example { 
        int foo; 
    
        example() { 
        int bar; 
    
        [this]() { 
         foo = {}; 
         bar = {}; // error: 'bar' is not captured 
        }(); 
    
        [&]() { 
         foo = {}; 
         bar = {}; 
        }(); 
        } 
    }; 
    

    すべてのローカル変数が破壊されていますようご閉鎖は、メンバ関数のように、囲みスコープの外で呼び出される場合は、[this]を使用する場合があります。

    struct example { 
        int value = 42; 
    
        example() { 
        frobnicate = [this]() { 
         std::cout << value << std::endl; 
        }; 
        } 
    
        std::function<void()> frobnicate; 
    }; 
    
    example x; 
    x.frobnicate(); 
    

    あなたの閉鎖を囲むスコープ内で呼び出される場合、ローカル変数がまだ生きているだろうとあなたは、ローカルコードの一部のように、[&]を使用する場合があります。

    struct example { 
        int value = 42; 
    
        example() { 
        int values[] = {1, 2, 3}; 
    
        std::for_each(std::begin(values), std::end(values), [&](int& v) { 
         std::cout << v * value << std::endl; 
        }); 
        } 
    }; 
    
    関連する問題