为什么我不能在lambda捕获此通过引用(“&这”)?(Why can't I captur

2019-09-01 16:04发布

我明白捕捉到正确的方法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.

Answer 1:

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

capture:
    identifier
    & identifier
    this

你可以看到, &this在语法上不容许。 这是不允许的原因是因为你绝不会想捕捉this引用,因为它是一个小的常量指针。 你永远只能希望按值传递它-所以语言只是不支持拍摄this作为参考。

为了捕捉this明确地可以使用[this]作为lambda-introducer

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

capture-default:
    &
    =

这意味着捕获自动任何我使用,通过引用( & )或值( =分别) -但是治疗this是特殊的-在两种情况下它被用于先前给出(即使有一个缺省捕获的原因值捕获& ,这通常由参考装置捕获)。

5.1.2.7/8:

对于名称查找(3.4)的目的,在确定的类型和值this (9.3.2)和转化ID-表达式中使用参照非静态类成员变成类成员访问表达式(*this) (9.3.1),则化合物-语句[拉姆达OF]在λ-表达的上下文中考虑。

所以拉姆达行为,如果它是包围部件功能的一部分(在你的例子一样使用名称的使用,当成员名称x ),所以它会产生的“隐性习惯” this就像一个成员函数一样。

如果一个lambda捕获包括捕获,默认是&在λ-捕获的标识不得由之前& 。 如果λ-捕获包括捕获默认即=时,λ-捕获不得含有this ,并且它包含每个标识符应由前面& 。 标识符或this不应出现一次以上的λ-捕获。

因此可以使用[this][&][=][&,this]作为lambda-introducer以捕获this由值指针。

然而[&this][=, this]是形成不良。 在最后一种情况GCC forgivingly警告为[=,this]explicit by-copy capture of 'this' redundant with by-copy capture default而不是错误。



Answer 2:

由于标准没有&this在捕获列表:

N4713 8.4.5.2捕获:

lambda-capture:
    capture-default
    capture-list
    capture-default, capture-list

capture-default:
    &
    =
capture-list:
    capture...opt
    capture-list, capture...opt
capture:
    simple-capture
    init-capture
simple-capture:
    identifier
    &identifier
    this
    * this
init-capture:
    identifier initializer
    &identifier initializer
  1. 对于拉姆达捕获的目的,表达可能引用本地实体如下:

    7.3该表达式可能引用*此。

因此,标准保证this*this是有效的,而&this是无效的。 此外,捕获this意味着捕捉*this (这是一个左值,对象本身) 作为参考而不是捕获this 通过值指针!



文章来源: Why can't I capture this by-reference ('&this') in lambda?
标签: c++ c++11 lambda