61

でラムダを書くとき[=]、それはすべてのローカル変数が作成された構造体のメンバーにコピーされることを意味しますか、それともラムダで実際に使用されるものだけを想定できますか?例えば:

void f()
{
    vector<int> v(10000);
    const int n = 5;
    const int DivByNCnt = count_if(istream_iterator<int>(cin), istream_iterator<int>(), 
          [=](int i)
          {
             return i % n == 0;
          });
}

次のうち、正しいものはどれですか?

  • nとvの両方がコピーされます
  • nはコピーされますが、vはコピーされません
  • nはコピーされますが、vは、実装/最適化の設定に応じてコピーされる場合とされない場合があります。

引数のために、vectorのコピーコンストラクターに副作用があるとします。

4

2 に答える 2

63

いいえ。これは、アンビエントスコープのすべてのローカル変数がラムダの本体内でルックアップできることを意味します。アンビエントローカル変数の名前を参照する場合にのみ、その変数がキャプチャされ、値によってキャプチャされます。

「何でもキャプチャ」の省略形=であり&、基本的には「私が何を意味するのかを理解する」ようにコンパイラーに指示する単なる構文糖衣です。


5.1.2 / 11-12からの正式なリファレンス:

ラムダ式に関連するcapture-defaultがあり、その複合ステートメントodr-uses [...]が自動保存期間の変数であり、odr-usedエンティティが明示的にキャプチャされていない場合、odr-usedエンティティは次のようになります。暗黙的にキャプチャされます[...]

エンティティは、明示的または暗黙的にキャプチャされた場合にキャプチャされます。

「 capture-default」はとを指すことに[=]注意してください[&]。繰り返しますが、capture-defaultを指定しても何もキャプチャされません。odrのみ-変数を​​使用します。

于 2013-03-25T10:22:40.767 に答える
22

いいえ!(ありがたいことに)

コードをインストルメント化して、コンパイラーが実際に実行するかどうかを確認できます。たとえば、gcc4.8.0は準拠しているようです。


規格が実際に義務付けているもの(逆方向に機能する)について:

§5.1.2/14エンティティが暗黙的にキャプチャされ、capture-defaultがである場合、またはエンティティが。を含まないキャプチャで明示的にキャプチャされている場合、エンティティはコピーによってキャプチャされます。コピーによってキャプチャされたエンティティごとに、名前のない非静的データメンバーがクロージャタイプで宣言されます。=&

$ 5.1.2 / 11ラムダ式に関連するcapture-defaultとその複合ステートメントodr-uses(3.2)thisまたは自動保存期間の変数があり、odr-usedエンティティが明示的にキャプチャされていない場合、odr-usedエンティティは暗黙的にキャプチャされると言われます; このようなエンティティは、ラムダ式の到達範囲内で宣言されるものとします。

§5.1.2/9最小の囲みスコープがブロックスコープ(3.3.3)であるラムダ式は、ローカルラムダ式です。その他のラムダ式では、ラムダイントロデューサーにキャプチャリストを含めることはできません。ローカルラムダ式の到達スコープは、最も内側の無名関数とそのパラメーターまでの範囲スコープのセットです。[注:この到達範囲には、介在するラムダ式が含まれます。—エンドノート]

于 2013-03-25T10:26:15.777 に答える