6

ラムダ関数と変数をキャプチャするメカニズムを理解するのに苦労しているので、少しテストを行って、本当に奇妙な結論に達しました。あれは:

class ClassA
{
public:
  std::function<void()> lambda;
  void DoYourStuff()
  {
    int x;
    x = 1;
    lambda = [=] () { printf("A %d\n", x);};
    lambda();
    x = 2;
    lambda(); 
  }
};

class ClassB
{
public:
  std::function<void()> lambda;
  int x;
  void DoYourStuff()
  {
    x = 1;
    lambda = [=] () { printf("B %d\n", x);};
    lambda();
    x = 2;
    lambda(); 
  }
};

注:違いはx変数の配置のみです。ClassAとClassBの関数の出力は異なります。

A 1
A 1
B 1
B 2

だから私の質問は:

  1. これは望ましい動作ですか?
  2. ClassAで[=]の代わりに[&]を使用した場合、それらのラムダは同一でしょうか?
  3. [=]が実際にいつコピーを作成するかについての一般的なルールはありますか?
  4. ラムダによる変数のキャプチャはいつ発生するはずですか?
  5. ラムダに変数の再キャプチャを強制することはできますか?

ありがとう

4

1 に答える 1

11

x1つ目は、ローカル変数を値でキャプチャします。1コピーが変更されていないため、両方の時間に印刷されます。

2つ目は、メンバー変数thisはなく、ローカルの準変数をキャプチャしますx。したがって、本体はと同等であり、変更後にprintf("%d\n", this->x);の新しい値を出力します。2x

明示的にキャプチャする場合x(つまり[x](){...})、最初の結果と同じ結果が表示されます。

これは望ましい動作ですか?

これは、言語標準で指定されている動作です。

ClassAで[=]の代わりに[&]を使用した場合、それらのラムダは同一でしょうか?

いいえ。ただし、どちらも同じ出力を生成します。x最初のものは参照によってローカルをキャプチャするので、それへの変更が表示されます。

[=]が実際にいつコピーを作成するかについての一般的なルールはありますか?

はい、ラムダが作成されたときに変数をコピーします。

ラムダによる変数のキャプチャはいつ発生するはずですか?

ラムダが作成されたとき。

ラムダに変数の再キャプチャを強制することはできますか?

いいえ。値によってキャプチャされると、変数の独自のコピーがあり、元の変数にアクセスする方法はありません。オリジナルへの変更を確認する必要がある場合は、参照によってキャプチャします(オブジェクトの存続期間に注意してください)。

于 2012-09-27T13:42:25.947 に答える