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

Arm*_*yan 61 c++ lambda capture c++11

当我写一个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;
          });
}
Run Code Online (Sandbox Code Playgroud)

如果有的话,以下哪一项是正确的?

  • n和v都将被复制
  • n将被复制,v将不会
  • n将被复制,v可能会也可能不会被复制,具体取决于实施/优化设置.

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

Ker*_* SB 63

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

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


5.1.2/11-12的正式参考:

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

如果明确或隐式捕获实体,则捕获该实体.

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

  • 我毫不怀疑你是对的,但你有什么参考吗? (3认同)

Mat*_* M. 22

没有!(谢天谢地)

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


至于标准实际要求(向后工作):

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

$ 5.1.2/11如果lambda表达式具有关联的capture-default及其复合语句odr-uses(3.2)this或具有自动存储持续时间的变量且未明确捕获odr-used实体,则使用odr-used据说实体被隐含地捕获 ; 这些实体应在lambda表达式的范围内声明.

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