列出生成器(lambda的向量)会导致通过引用捕获的非常奇怪的行为

  • 本文关键字:引用 非常 出生 lambda 向量 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() << " ";
}
}

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

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

当我将捕获子句更改为 [=] 时,它可以工作,但在我的实际应用程序中,输入会非常大,所以我宁愿尽可能少地复制。

编辑:我应该澄清我正在寻找什么。我想制作一个 N 个函数的向量,[f_0,f_1,...f_N],这样在调用 f_i() 时,它会为一些大型(已知)函数 F 和大型V_i调用 F(V_i)。

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

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

奇怪的是,您坚持使用对整数值的引用。 编译器可能正在尽最大努力内联这些并仅使用普通副本,但您应该考虑到,当您有引用时,您通常可以期望生成其他指令以取消对值的引用。 对于基元类型,只需复制。

哦,绝对按价值捕获i!! 作为风格问题,我更喜欢明确我的捕获:

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

最新更新