c++ - lambda 的捕获机制

标签 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 中使用 [&] 而不是 [=],这些 lambda 是否相同?
  3. 关于 [=] 实际复制的时间是否有一些通用规则?
  4. lambda 捕获变量的确切时间应该在什么时候发生?
  5. 我可以强制 lambda 重新捕获变量吗?

谢谢

最佳答案

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

第二个捕获局部准变量this不是成员变量x。所以正文等价于 printf("%d\n", this->x);,并且会在你更改 后打印 2 的新值x.

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

Is this the desired behaviour?

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

if i used [&] instead of [=] in ClassA, would those lambdas be identical?

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

Is there some general rule as to when [=] actually makes copy?

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

When exactly is the capturing of variables by lambdas supposed to happen?

创建 lambda 时。

Can I force lambda to do a re-capture of variables?

没有。一旦它被值捕获,它就有了自己的变量拷贝,无法访问原始变量。如果您需要查看对原始文件的更改,则通过引用捕获(并注意对象生命周期)。

关于c++ - lambda 的捕获机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12622627/

相关文章:

c++ - 如何禁用隐式 lamba 变量捕获?

java - 将 java 转移到 c++

c++ - 用于理解重构代码的 C/C++ 包

c# - 遍历表达式树并提取参数

c# - 在 C# 中的数据模型上运行 lambda 时不支持的异常

node.js - Elastic Beanstalk 上的 AWS lambda 到 Nodejs 项目的用例

c++ - SFINAE 自动检查函数体是否在没有明确约束的情况下编译

c++ - 寻找最小的产品

c++ - 谁能解释为什么输出大于分配的内存?

c# - 如何在 Enumerable.Distinct() 中使用 lambda 表达式