我似乎错过了 C++ 中 lambda 机制的一些要点。代码如下:
std::vector<int> vec (5);
int init = 0;
std::generate(begin(vec), end(vec), [init]() mutable { return ++init; });
for (auto item : vec) {
std::cout << item << " ";
}
std::cout << std::endl << init << std::endl;
如果没有 mutable
它将无法编译,因为我正在更改 lambda 中的 init
。
现在,据我所知,每个 vector 的项目都会调用 lambda,其中 init
的 new fresh copy 为 0。
因此,每次都必须返回 1。
但是这段代码的输出是:
1 2 3 4 5
0
看起来 generate
在其执行开始时通过复制 init
一次 捕获。但为什么?它应该像这样工作吗?
最佳答案
Now, as I understand lambda is called for each vector's item with a new fresh copy of init which is 0.
这是不正确的。 lambda 只是另一种创建类并为其提供 operator()
的方法。 lambda 的 []
部分描述了成员变量以及它们是通过引用还是通过值捕获的。 lambda 的 ()
部分是 operator()
的参数列表,而 {}
部分是该函数的主体。 mutable
部分告诉编译器将 operator()
设为非 const
,因为它默认为 const
。
所以
[init]() mutable { return ++init; }
变成
struct compiler_generated_name
{
int init; // we captured by value
auto operator()() // since we used mutable this is non const
{
return ++init;
}
};
为了简洁起见,我在这里使用了结构体,但 lambda 被指定为类类型,因此可以使用 class
。
这意味着 init
与上次迭代中的 init
相同,因为您只捕获一次。记住这一点很重要
auto generate_lambda()
{
int foo = 0;
return [&foo](){ return ++foo; };
}
当函数返回并使用它是未定义的行为时,将为您留下对 foo
的悬空引用。
关于c++ - 在 C++ 中将参数传递给 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37221259/