[=]是否意味着将复制所有局部变量?

时间:2013-03-25 10:19:14

标签: c++ c++11 lambda capture

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

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可能会也可能不会被复制,具体取决于实施/优化设置。

假设为了论证,vector的复制构造函数有副作用。

2 个答案:

答案 0 :(得分:63)

没有。它只是意味着来自环境范围的所有局部变量都可用于在lambda体内查找。只有 if 你引用环境局部变量的名称才能捕获该变量,并且它将被值捕获。

“捕获任何东西”的缩写=&只是语法糖,本质上是告诉编译器“弄明白我的意思”。


5.1.2 / 11-12的正式参考:

  

如果lambda表达式具有关联的 capture-default 且其复合语句 odr-使用具有自动存储持续时间和odr的变量 - 未明确捕获使用过的实体,然后使用odr使用的实体隐式捕获 [...]

     

如果实体是捕获,如果它是显式或隐式捕获的。

请注意,“ capture-default ”指的是[=][&]。要重复,指定捕获默认值不会捕获任何内容;只有使用变量的odr。

答案 1 :(得分:22)

没有! (谢天谢地)

您可以检测代码以检查编译器是否实际执行了(或不执行)。例如,gcc 4.8.0似乎符合要求。


关于标准实际要求的内容(向后工作):

  

§5.1.2/ 14如果隐式捕获并且捕获默认值为=,或者如果使用不捕获的捕获显式捕获实体,则捕获实体包括&。对于由副本捕获的每个实体,在闭包类型中声明一个未命名的非静态数据成员。

     

$ 5.1.2 / 11如果lambda表达式具有关联的capture-default及其compound-statement odr-uses(3.2)this或具有自动存储持续时间的变量且odr-used实体不是明确捕获,然后然后使用odr使用的实体被隐式捕获;这些实体应在lambda表达式的范围内声明。

     

§5.1.2/ 9 lambda表达式是一个局部lambda表达式,其最小的封闭范围是块作用域(3.3.3);任何其他lambda-expression在其lambda-introducer中都不应该有一个capture-list。本地lambda表达式的到达范围是封闭范围的集合,包括最里面的封闭函数及其参数。 [注意:这个范围包括任何介入的lambda表达式。 - 后注]