32

以下のコードは 0 を出力しますが、1 が表示されることを期待しています。私の結論は、キャプチャされたパラメーターを実際に関数に渡すことによってラムダ関数が呼び出されないということです。これはより直感的です。私は正しいですか、それとも何か不足していますか?

#include <iostream>
int main(int argc, char **argv){
  int value = 0;
  auto incr_value  = [&value]() { value++; };
  auto print_value = [ value]() { std::cout << value << std::endl; };
  incr_value();
  print_value();
  return 0;
}
4

3 に答える 3

29

Lambda関数、キャプチャされたパラメーターを実際に関数に渡すことによって呼び出されます。

valueラムダが定義された(そしてvalueキャプチャされた)ポイントで0に等しい。値でキャプチャしているので、キャプチャ後に何をするかは問題ではありませんvalue

参照によってキャプチャした場合はvalue、キャプチャのポイントが同じ(ラムダ定義)であっても、キャプチャされたオブジェクトの現在の値を出力し、そのときに作成されたオブジェクトのコピーではないため、1が出力されます。キャプチャされました。

于 2012-07-22T10:41:40.943 に答える
14

はい、ラムダが呼び出されたときではなく、ラムダが宣言された時点でキャプチャが行われます。ラムダは、コンストラクターがキャプチャーされた変数をパラメーターとして取り、それらを対応するメンバー変数 (キャプチャーモードに応じて値または参照のいずれか) に割り当てる関数オブジェクトと考えてください。ラムダの実際の呼び出しには魔法はありません。基になる関数オブジェクトの通常operator()の呼び出し。

コール ポイントで何かをキャプチャすることはあまり意味がありません。ラムダが別の関数にパラメータとして返されるか渡され、そこで呼び出された場合、何がキャプチャされるのでしょうか? 実際にこのように動作する言語があります。関数内の変数を参照する場合、呼び出し時点で現在スコープ内でx呼び出されている変数を参照すると見なされます。xこれは動的スコープと呼ばれます。プログラムについての推論をより簡単にするため、ほとんどの言語で使用される代替手段は、字句スコープと呼ばれます。

http://en.wikipedia.org/wiki/Lexical_scoping#Lexical_scoping_and_dynamic_scoping

于 2012-07-22T12:32:46.197 に答える
5

問題は、印刷関数が参照ではなく値によってキャプチャされていることです。

#include <iostream>
int main(int argc, char **argv){
  int value = 0;
  auto incr_value  = [&value]() { value++; };
  auto print_value = [ value]() { std::cout << value << std::endl; };
  auto print_valueref = [ &value]() { std::cout << value << std::endl; };

  incr_value();
  print_value();
  print_valueref();
  return 0;
}

期待どおりに 0 と 1 を出力します。最初のものは値によってキャプチャされ、キャプチャの時点で値を出力します。2 つ目は参照を取得し、その値を出力します。

于 2012-07-22T21:44:53.010 に答える