我知道我们必须捕获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
在捕获列表中是无效的。
发布于 2021-07-08 19:27:07
void func ()
{
[a = this->a] () { std::cout << a; } ();
}
您需要指定变量的名称才能在lambda中访问它。
编辑:
引擎盖下的Lambda:
当执行lambda定义时,对于lambda捕获的每个变量,在lambda中创建该变量的克隆(具有相同的名称)。此时,这些克隆的变量是从同名的外部作用域变量初始化的。
所以[this->a]
没有任何意义。编译器需要为捕获的变量分配空间,并且为了使内存可访问,它需要一个名称。
发布于 2021-07-08 19:40:05
,但我的问题是,为什么这是无效的
首先要理解的是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;
};
现在,如果您允许expression this->a
出现在捕获列表中,应该如何将其转换为类成员?可以说,它可以称为a
,但如果允许使用表达式this->a
,为什么不允许使用this->a.size()
(假设a
为std::vector
)?那么它将如何命名呢?
由于这个问题可以通过命名捕获或整体捕获this
轻松解决,因此没有充分的理由在其中添加处理复杂的表达式。
发布于 2021-07-08 19:39:56
这只是什么语法有效和什么语法无效的问题。您的问题不是特定于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](){};
}
https://stackoverflow.com/questions/68300641
复制相似问题