2016-08-03 6 views
4

C++ 14の標準ドラフトN4140 5.1.2.12 [expr.prim.lambda]の例はあまり理解できません。 ラムダのキャプチャされていない変数の使用

これは明示的にこれをキャプチャしない関連するキャプチャのデフォルトであり、自動保存期間を持つ変数です(initcaptureに関連付けられた非静的データを参照するために見つかったid式はすべて除外されます)。メンバーは)、(暗黙的実体をキャプチャすると言われている、すなわち、このまたは変数)化合物-if文:

  • ODR-使用するエンティティ、または
  • 名潜在的に評価された式どこでエンティティを包含式の完全表現は、lの到達範囲内で宣言された汎用ラムダパラメータに依存するambda-expression。

[例:

void f(int, const int (&)[2] = {}) { } // #1 
void f(const int&, const int (&)[1]) { } // #2 
void test() { 
    const int x = 17; 
    auto g = [](auto a) { 
    f(x); // OK: calls #1, does not capture x 
    }; 
    auto g2 = [=](auto a) { 
    int selector[sizeof(a) == 1 ? 1 : 2]{}; 
    f(x, selector); // OK: is a dependent expression, so captures x 
    }; 
} 

末端例]

全てのこのような暗黙的に捕捉されたエンティティは、ラムダ式の到達範囲内で宣言されなければなりません。

[注:ネストされたラムダ式によるエンティティの暗黙的なキャプチャは、ラムダ式を含む暗黙のキャプチャを引き起こす可能性があります(下記参照)。これを暗黙的にodrで使用すると暗黙的に取得される可能性があります。末端ノート]

私は、そのため#1呼び出しはエラー(撮影していない変数を使用してについて何か)につながるフレーズa lambda-expression with an associated capture-defaultの始まりはどんな暗黙の捕獲を禁止するべきだと思った(そしてそれはコメントで確認しています)。それはどうやって動くの? fの最初の議論は何でしょうか? test()スコープを終了した後にgが呼び出されるとどうなりますか? #1の署名をvoid(const int&)に変更するとどうなりますか?

-

更新:どのように動作するのか説明してくれてありがとうございます。後で、私はこの事件についての標準への参照を見つけて投稿しようとします。

+1

'x'はconst式です。これはODRであり、参照のため#2だけに使用されます。 – Jarod42

+1

つまり、 'g'はあたかも' {f(17);}のように振る舞います。 } '。 –

答えて

0

T.C.彼のコメントでは、コンパイル時にxが知られているので、#1はキャプチャを必要としないため、ラムダに焼き付けられます。コンパイル時に関数fがどのようにわかっているのと違って、キャプチャする必要はありません。あなたは今、スタックに変更することが対象としている定数のアドレスを渡すしようとしているint const &fの署名を変更した場合

は、私は信じて、それが値または参照によってxを取り込む必要となります。

関連する問題