lambda的捕获机制

时间:2012-09-27 13:33:13

标签: c++ lambda

我无法理解lambda函数和捕获变量的机制,所以我做了一些测试并得出了非常奇怪的结论。那就是:

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中使用[&amp;]而不是[=],那些lambda会不会相同?
  3. 是否有一些关于何时[=]实际复制的一般规则?
  4. 究竟是什么时候应该发生lambdas对变量的捕获?
  5. 我可以强制lambda重新捕获变量吗?
  6. 由于

1 个答案:

答案 0 :(得分:11)

第一个按值捕获局部变量x;所以它会两次打印1,因为它的副本没有改变。

第二个捕获局部准变量this成员变量x。因此,正文与printf("%d\n", this->x);相同,并且在您更改2后会打印x的新值。

如果您要明确捕获x(即[x](){...}),那么您将看到与第一个相同的结果。

  

这是理想的行为吗?

这是语言标准指定的行为。

  

如果我在ClassA中使用[&amp;]而不是[=],那些lambdas是否相同?

不,但两者都会产生相同的输出。第一个将通过引用捕获本地x,因此您将看到对它的更改。

  

是否有一些关于何时[=]实际制作副本的一般规则?

是的,它在创建lambda时复制变量。

  

究竟是什么时候应该发生lambdas对变量的捕获?

创建lambda时。

  

我可以强制lambda重新捕获变量吗?

没有。一旦它被值捕获,它就有自己的变量副本,无法访问原始变量。如果您需要查看原始更改,请通过引用捕获(并注意对象生存期)。