c ++ 11ラムダは、使用しない変数をキャプチャしますか?


123

[=]すべてのローカル変数をラムダ内の値でキャプチャすることを示すために使用すると、コピーされる関数内のすべてのローカル変数、またはラムダによって使用されるすべてのローカル変数だけになりますか?

したがって、たとえば、私が持っている場合:

vector<int> my_huge_vector(100000);
int my_measly_int;
some_function([=](int i){ return my_measly_int + i; });

my_huge_vectorはラムダで使用していなくてもコピーされますか?

回答:


114

キャプチャリストで明示的に指定された各変数がキャプチャされます。デフォルトのキャプチャでは、(a)キャプチャリストで明示的に指定されていない変数と(b)ラムダ式の本文で使用されている変数の両方がキャプチャれます。変数に明示的な名前が付けられておらず、ラムダ式で変数を使用しない場合、変数はキャプチャされません。あなたの例でmy_huge_vectorは、キャプチャされていません。

C ++ 11§5.1.2[expr.prim.lambda] / 11によると:

場合はラムダ式が関連付けられていキャプチャー・デフォルトおよびその化合物ステートメント ODR-用途 thisや自動記憶域期間とを備えた可変ODR-使用エンティティ明示的に捕獲されていないが、その後、ODR-使用エンティティは、暗黙的に取得されたと言われています。

ラムダ式には、関連付けられたキャプチャのデフォルトがあります。デフォルトでは、を使用して変数を値でキャプチャします[=]

変数が使用されている場合(「定義済み」という用語の「使用済み」という意味)は、暗黙的にキャプチャされた変数です。my_huge_vectorラムダ式の本体(「複合ステートメント」)ではまったく使用しないため、暗黙的にキャプチャされません。

§5.1.2/ 14を続行するには

次の場合、エンティティはコピーによってキャプチャされます

  • 暗黙的にキャプチャされ、capture-defaultは、=または
  • を含まないキャプチャで明示的にキャプチャされ&ます。

あなた以来my_huge_vectorISが暗黙的にキャプチャされませんし、それが明示的に捕獲されていない、それはコピーまたは参照で、すべてでキャプチャされていません。


10
あなたは聖なる言葉を持っていますか
GManNickG 2011年

ただし、詳細をすべて理解するには、5.1.2の全体が重要であると言います。そのセクションでは多くの技術用語が定義されており、ラムダ式のさまざまなコンポーネントの定義は必然的に絡み合っているため、「これがXであり、これがXである」と明確に述べる短い引用符を引き出すことは困難です。
James McNellis、2011年

少なくとも明示的に名前が付けられた変数については、そのような最適化は許可されていないことを示すここでの注意のためにpingを実行します。どこに線を引くかわかりません。
GManNickG

@GManNickG:それはいくつかの強力なトローリングです;-)。実際にこのページをポイントしていることに気付くまでに、そのリンクを3回クリックする必要がありました...:-O [いずれにせよ、明日の朝オフィスに来て更新するときに、言語仕様を読み直します。適切な答え。]
James McNellis、2012年

おっと、ごめんなさい!!! 私の質問に答えました、代わりにここにリンクするつもりでした。それはひどく混乱したに違いない。
GManNickG 2012年

16

いいえ、my_huge_vectorキャプチャされません。使用されている[=]すべての変数がラムダにキャプチャされることを意味します。


6
うん。ただし、usedは技術的な用語であり、実際に使用されている1つの定義ルールを意味します。したがって、たとえば、を検討してくださいvoid f() { const int size(10); [] { int x[size]; }; }。ここでsizeは、キャプチャされていませんが、ODRの意味で使用されていないため、問題ありません。(Visual C ++ 2010はこのコードを受け入れません。VC10のリリース後に仕様が変更されたか、バグが原因であると考えられます。おそらくこれは次のバージョンで修正されるでしょう。g++ 4.5.1はそれを受け入れます。)
James McNellis

@JamesMcNellisは心配しないで、MSVCは今日でも臭いがらくたの山です。cf. godbolt.org/z/vHnnCX(lulzについてはgccをチェックイン)。それは言った; 評価された式に現れる識別子がODRに使用されない理由がわかりません。このケースは間違いなくODRを使用していると思います。ただし、constexprとして解釈される可能性がある場合を除き、値のみが有用ですか?私は、コンパイラがconst何かが潜在的に変異しないと想定しているのかどうかわかりません。たぶん超攻撃的な最適化フラグOXか何かでない限り。
v.oddou
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.