是否暗示所有的局部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式。 – 注意]