列出生成器(lambdas的向量)列表会导致非常奇怪的行为,即按引用捕获

And*_*nes 4 c++ lambda

以下代码与我的实际应用程序非常相似。基本上,我正在尝试创建函数向量,以便可以分段生成非常大的输出。我不完全理解按引用[&]进行捕获的工作方式/应该如何工作,并且导致某些奇怪的行为。

#include <iostream>
#include <functional>
#include <vector>

using namespace std;

template <typename T>
T add(const T& a, const T& b) {
  return a + b;
}

template <typename T>
T add(const T& a, const T& b, T x) {
  return (add<T>(a,b)*x);
}


int main() {
  std::cout << "Hello World!\n";

  vector<function<long ()>> funks;
  for (long i = 1; i < 12; ++i) {

    //auto funky = std::bind(add<int>, i, i*i);

    std::cout << "PROOF: " << add(i, i*i, 2L) << std::endl;


    function<long ()> funky = [&]() -> long {
      long V = i;
      return add(V, V*V, 2L);
      };

    funks.push_back(funky);
  }

  for (auto&& x : funks) {
    std::cout << x() << " ";
  }
}
Run Code Online (Sandbox Code Playgroud)

在funk中运行每个x的输出是:[312,312,312 ... 312]对应于i = 13

但是,我不明白为什么会这样,因为我为每个lambda重新初始化了V,并且输出应为[4,12,24,40,... 264]

当我将capture子句更改为[=]时,它可以工作,但是在我的实际应用程序中,输入将非常大,因此我希望复制次数尽可能少。

编辑:我应该明确说明我在寻找什么。我想制作一个由N个函数组成的向量[f_0,f_1,... f_N],这样,当调用f_i()时,它将为某些大型(已知)函数F和大型V_i调用F(V_i)。

我想通过引用捕获的原因是我甚至不想复制V_i,但是实现的结果是每个f_i()最终都会调用F(V_N)

pad*_*ddy 7

您正在i循环中通过引用自动捕获,但这仅是绑定。该值直到循环之后才调用lambda 才真正使用。届时,每个调用都将捕获的“引用i”(实际上是未定义的行为,因为它i不再在范围内),将其取消引用并将值存储在中V。你知道其余的。

奇怪的是,您坚持使用对整数值的引用。编译器可能会尽力内联这些代码并仅使用普通副本,但是您应该考虑到,当您拥有引用时,通常会期望生成其他指令以将其取消引用为值。对于原始类型,只需复制即可。

哦,绝对是i按价值捕获的!!!从风格上讲,我更想明确地描述自己的拍摄内容:

function<long ()> funky = [i]() -> long {
    long V = i;
    return add(V, V*V, 2L);
};
Run Code Online (Sandbox Code Playgroud)