是否暗示所有的局部variables将被复制?

当我用[=]写一个lambda时,是否意味着我所有的局部variables都将被复制到创build的结构的成员中,或者我可以假设只有那些实际在lambda中使用的variables? 例如:

 void f() { vector<int> v(10000); const int n = 5; const int DivByNCnt = count_if(istream_iterator<int>(cin), istream_iterator<int>(), [=](int i) { return i % n == 0; }); } 

以下哪一项是真的?

  • n和v都将被复制
  • n将被复制,v不会
  • n将被复制,v可能会或可能不会被复制,取决于implmenentation /优化设置。

假设参数的缘故,vector的拷贝构造函数有副作用。

不,这只是意味着来自环境范围的所有局部variables都可用于lambda体内的查找。 只有您引用环境局部variables的名称时,该variables才会被捕获,并且会被值捕获。

“捕获任何东西”shorthands =&只是语法糖,实质上是告诉编译器“弄清楚我的意思”。


来自5.1.2 / 11-12的正式参考:

如果lambdaexpression式具有关联的capture-default,并且其复合语句 odr-使用具有自动存储持续时间的variables,并且未明确捕获odr-used实体,则称odr-used实体被隐含地捕获 […]

如果明确或隐含地捕获实体,则捕获该实体。

请注意,“ capture-default ”是指[=][&] 。 重复一遍,指定capture-default不会捕获任何东西; 只有odr – 使用一个variables。

没有! (谢天谢地)

你可以testing你的代码来检查你的编译器是否真的做了(或不)。 例如gcc 4.8.0似乎是兼容的。


至于标准实际要求的是什么(倒退):

§5.1.2/ 14如果一个实体被隐式捕获并且捕获默认值为=或者如果明确捕获到一个不包含&的捕获,则该实体被捕获 。 对于通过复制捕获的每个实体,在封闭types中声明一个未命名的非静态数据成员。

$ 5.1.2 / 11如果一个lambdaexpression式有一个关联的capture-default和它的复合语句odr-使用(3.2) this或者一个variables具有自动存储持续时间并且odr-used实体没有被明确地捕获, 那么odr-据说使用的实体被隐式捕获 ; 这些实体应该在lambdaexpression式的范围内声明。

§5.1.2/ 9最小封闭范围是块范围(3.3.3)的lambdaexpression式是一个本地lambdaexpression式; 任何其他lambdaexpression式的lambda-introducer中都不应该有捕获列表。 本地lambdaexpression式的扩展范围是包含最内部封闭函数及其参数的封闭范围的集合。 [注意:这个范围包括任何介入的lambdaexpression式。 – 注意]