在 lambda 中,引用的按值捕获是否复制底层对象?

如果在 lambda 中通过值捕获引用类型的变量,是复制被引用的对象还是通过引用捕获它?

有问题的小样本:

#include <iostream>


struct Test {
int a;
};


void testFunc(const Test &test) {
auto a = [=] {
// is 'test' passed to closure object as a copy
// or as a reference?
return test.a;
} ();
std::cout << a;
}


int main() {
Test test{1};
testFunc(test);
}
21113 次浏览

可编译的例子:

class C
{
public:
C()
{
i = 0;
}


C(const C & source)
{
std::cout << "Copy ctor called\n";
i = source.i;
}


int i;
};


void test(C & c)
{
c.i = 20;


auto lambda = [=]() mutable {


c.i = 55;
};
lambda();


std::cout << c.i << "\n";
}


int main(int argc, char * argv[])
{
C c;
test(c);


getchar();
}

结果:

Copy ctor called
20

我想,C + + 标准的这一段应该是适用的:

5.1.2 Lambda 表达式

(...) 14.如果实体是隐式捕获的,并且 Catch-default 捕获-默认是 = 或者如果它是显式的,那么它将被 收到捕获 对于通过拷贝捕获的每个实体,一个未命名的非静态 数据成员是在闭包类型中声明的。这些成员的声明顺序未指定。 此类数据成员的类型是相应捕获的实体的类型,如果该实体不是 引用对象 或引用的类型。[ 注意: 如果捕获的实体是对 函数,则对应的数据成员也是对函数的引用。ー 尾注]

这实际上是有意义的——如果局部变量是通过值传递的,而参数是通过引用传递的,那么在函数中,“扮演”局部变量的角色,为什么它会通过引用而不是通过值传递呢?