【问题标题】:c++ closure with unexpected resultc++ 闭包,结果出乎意料
【发布时间】:2018-06-06 03:08:15
【问题描述】:

我正在测试一些关于闭包的特性,但我遇到了一些问题,这里有一些代码,有一个 3 个 lambda 函数的向量,这些函数捕获内部的局部变量 BuildFns ,所有 i 的内存位置都是相同的,但是,只有来自主函数的第一次调用实际输出 3,当我们在 main 中调用它们时,我们是否应该期望向量输出 3 中的所有函数?

#include <iostream>
#include <vector>
using namespace std;
auto BuildFns() {
  vector<function<void()>> vec;
  for (int i = 0; i < 3; i++) {
    cout << &i << '\n';
    vec.push_back([&i]() {
      cout << i << endl;
      cout << &i << '\n';
    });
  }
  return vec;
}


auto main() -> int {
  auto vec = BuildFns();
  vec[0]();
  vec[1]();
  vec[2]();
}

输出:

0x7ffeedfa25c8
0x7ffeedfa25c8
0x7ffeedfa25c8
3
0x7ffeedfa25c8
-1581316512  // what's wrong with this i? isn't it contained in the closure environment and can't be written if it's still been accessed?
0x7ffeedfa25c8
-1581316512
0x7ffeedfa25c8

预期:

0xaddress_of_i
0xaddress_of_i
0xaddress_of_i
3
0xaddress_of_i
3
0xaddress_of_i
3
0xaddress_of_i

【问题讨论】:

  • 变量i 仅在循环内是局部的。一旦循环完成,变量就会超出范围并且它的生命周期结束,并且任何指向它的指针或引用都将悬空且无效。使用该引用会导致undefined behavior
  • @Someprogrammerdude 好的,我认为关闭会延长我的寿命

标签: c++ lambda closures


【解决方案1】:

这里的问题是,您正在通过引用 (&amp;i) 对超出范围 (i) 的局部变量进行捕获,此时 BuildFns() 返回。引用捕获也可以是指针,并且作为局部变量,在这种情况下可能是指向堆栈的指针。因此,您不应该对值随机变化感到惊讶。它所需要的只是 std::function 调用中的某种机制来写入堆栈,然后你的值就消失了。

如果您在创建闭包时确实想要 i 的值,请改为按值捕获。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-16
    • 2021-03-25
    • 2016-09-03
    • 1970-01-01
    • 2011-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多