我似乎忽略了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
。
现在,据我所知,lambda是为每个向量的项调用的,其中init
的new fresh copy为0,因此,每次都必须返回1,但这段代码的输出是:
- 1 2 3 4 5
0**
看起来generate
在执行开始时只通过copy init
捕获了一次。但是为什么呢?它应该这样工作吗?
5条答案
按热度按时间atmip9wb1#
现在,据我所知,为每个向量的项调用lambda,并使用init的新副本,其值为0。
这是不正确的。lambda只是创建类并为其提供
operator()
的另一种方式。lambda的[]
部分描述了成员变量以及它们是通过引用还是值捕获的。lambda的()
部分是operator()
的参数列表,{}
部分是该函数的主体。mutable
部分告诉编译器将operator()
设置为非const
,因为默认情况下它是const
。所以
变成
为了简化输入,我在这里使用了一个struct,但是lambda被指定为类类型,因此可以使用
class
。这意味着
init
与上次迭代中的init
相同,因为您只捕获过一次。将在函数返回时给您留下一个对
foo
的悬空引用,并且使用它是未定义的行为。zte4gxcn2#
lambda是编译器生成的结构,等效于:
因此,
init
只在lambda中被捕获和复制一次--多次调用lambda将不会再次捕获init
。nwwlzxa73#
您正在处理并看到init的初始值--根据您的期望,您可能要做的是通过引用捕获
init
.....kadbb4594#
你的错误在这里“现在,据我所知,lambda被称为 * 每个向量的项目 * 与一个新的新鲜副本的init是0”(我的斜体)。正如你所看到的,lambda是完全独立的,因此对向量代码一无所知。
item
的初始化发生在每次lambda形式本身被求值时(与每次结果值被调用时相反);这里,这意味着每次调用函数generate
时:就一次。pgvzfuti5#