为什么我不能在lambda中捕获这个引用('&this')?

我理解在lambda中捕获this (修改对象属性)的正确方法如下:

 auto f = [this] () { /* ... */ }; 

但是我很好奇以下的特点:

 class C { public: void foo() { // auto f = [] () { // this not captured auto f = [&] () { // why does this work? // auto f = [&this] () { // Expected ',' before 'this' // auto f = [this] () { // works as expected x = 5; }; f(); } private: int x; }; 

我感到困惑的(并希望得到回答)的原因是,为什么下面这样工作:

 auto f = [&] () { /* ... */ }; // capture everything by reference 

为什么我不能明确地通过引用来捕捉this

 auto f = [&this] () { /* ... */ }; // a compiler error as seen above. 

原因[&this]不起作用是因为它是一个语法错误。 lambda-introducer每个逗号分隔的参数都是一个capture

 capture: identifier & identifier this 

你可以看到, &this是不允许的语法。 它不被允许的原因是因为你永远不会想要通过引用来捕获它,因为它是一个小的const指针。 你只会想要传递它的价值 – 所以语言不支持通过引用来捕获。

要明确地捕获this你可以使用[this]作为lambda-introducer

第一个capture可以是一个capture-default是:

 capture-default: & = 

这意味着分别通过引用( & )或值( = )自动捕获任何我使用的内容 – 但是这种处理是特殊的 – 在这两种情况下,由于前面给出的原因(通过默认捕获& ,通常意味着通过引用捕获)。

5.1.2.7/8:

为了查找名称(3.4),确定this (9.3.2)的types和值,并使用(*this) (9.3.1)将涉及非静态类成员的id-expression式转换为类成员访问expression式, lambdaexpression式的复合语句被认为是在lambdaexpression式的上下文中。

所以当使用成员名称(就像在你的例子中使用名称x )时,lambdaperformance得好像是包含成员函数的一部分,所以它会像成员函数一样产生“隐式用法”。

如果一个lambda捕获包括一个捕获默认值是& ,lambda捕获中的标识符不应该在&之前。 如果一个lambda捕获包含一个=的捕获缺省值,那么lambda捕获不包含this并且它包含的每个标识符都应该以&为前缀。 一个标识符或者this在lambda-capture中不能出现一次以上。

所以你可以使用[this][&][=][&,this]作为lambda-introducer来按值捕获this指针。

然而[&this][=, this]是不合格的。 在最后一种情况下,gcc谨慎地警告[=,this] explicit by-copy capture of 'this' redundant with by-copy capture default而不是错误。