gpt4 book ai didi

c++ - 制作生成器列表(lambda 的 vector )会导致通过引用捕获的非常奇怪的行为

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:26:15 27 4
gpt4 key购买 nike

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

#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() << " ";
}
}

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

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

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

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

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

最佳答案

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

奇怪的是您坚持使用对整数值的引用。很可能编译器正在尽最大努力内联这些并只使用普通拷贝,但您应该考虑到当您有一个引用时,您通常可以期望生成附加指令以将其取消引用为一个值.对于原始类型,只需复制即可。

哦,肯定按值捕获 i!!!就风格而言,我更喜欢明确我的捕获:

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

关于c++ - 制作生成器列表(lambda 的 vector )会导致通过引用捕获的非常奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57471119/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com