仅捕获 lambda 中类的特定成员

问题描述 投票:0回答:4

我知道我们必须捕获 lambda 中的 *this 指针才能访问 lambda 中的任何成员变量。现在,为什么我不能仅捕获 lambda 内对象的单个成员?

 #include <iostream>

class Foo
{
public:
    Foo () : a(5) {}
    void func ()
    {
        [this->a] () { std::cout << a; } ();
    }

private:
        int a;
};

int main()
{
    Foo f;
    f.func();
}

上面的代码给我带来了语法错误,

<source>: In member function 'void Foo::func()':
<source>:9:14: error: expected ',' before '->' token
    9 |         [this->a] () { std::cout << a; } ();
      |              ^~
<source>:9:14: error: expected identifier before '->' token

我在 Godbolt 中尝试过这个。与 gcc 11.1 的组织

[编辑]我知道有多种方法可以捕获对象的单个成员,但我想了解为什么

this->member
在捕获列表中无效。

c++ lambda
4个回答
2
投票

但我的问题是为什么这无效

首先要了解的是 lambda 在幕后是如何表达的。编译器将其替换为具有重载

operator()
的匿名类。例如,以下 lambda:

[a](int b){return a + b;}

可以由编译器转换为以下类:

class __lambda_some_random_unique_identifier {
public:
    int operator() (int b) const {
        return a + b;
    }
private:
    int a;
};

现在,如果您允许表达式

this->a
出现在捕获列表中,那么应该如何将其转换为类成员?可以说,它可以被称为
a
,但如果你允许表达
this->a
,那么为什么不使用
this->a.size()
(假设
a
std::vector
)呢?那怎么命名呢?


由于问题可以通过命名捕获 捕获

this
轻松解决,因此没有充分的理由添加处理复杂表达式。


2
投票
void func ()
{
    [a = this->a] () { std::cout << a; } ();
}

您需要指定变量的名称才能在 lambda 中访问它。

编辑:

Lambda 的底层:

执行 lambda 定义时,对于 lambda 捕获的每个变量,都会在 lambda 内部创建该变量的克隆(具有相同的名称)。此时,这些克隆变量是从同名的外部作用域变量初始化的。

所以

[this->a]
没有意义。编译器需要为捕获的变量分配空间,并且为了使该内存可访问,它需要一个名称。


1
投票

这只是什么语法有效、什么语法无效的问题。您的问题并非特定于

this
。您也无法像这样捕获另一个对象的成员:

struct foo { int x; };

int main() {
    foo obj;
    foo* f = &obj;
    auto l = [f->x](){};
}

虽然这样还可以:

struct foo { int x; };

int main() {
    foo obj;
    foo* f = &obj;
    auto l = [x = f->x](){};
}

0
投票

如果您打算使用类成员,则公开指针是有意义的

this

class Foo
{
public:
    Foo () : a(5) {}
    void func ()
    {
        [this] () { std::cout << a; } ();
    }

private:
        int a;
};
© www.soinside.com 2019 - 2024. All rights reserved.