这个指针是如何被捕获的

How is the this pointer captured?

本文关键字:指针      更新时间:2023-10-16

考虑以下代码:

struct S
{
int x;
void f()
{
auto l = [&](){ x = 42; }; //this is implicitly captured here
}
};

§5.1.2/14规定:

如果实体是隐式捕获的,并且捕获默认值为=,或者如果实体是用不包括&的捕获显式捕获的;。

因此,我得出结论,this不是通过复制捕获的。但根据§5.1.2/15:

如果实体是隐式或显式捕获的,但不是通过复制捕获的,则通过引用捕获实体。未指定是否在通过引用捕获的实体的闭包类型中声明其他未命名的非静态数据成员。

this通过引用捕获。但现在§5.1.2/17规定:

[…]如果捕获了this,则this的每个odr使用都转换为对闭包类型的相应未命名数据成员的访问,[…]

据我所知,这意味着在对应于this指针的闭包类型中必须有一个未命名的数据成员。但由于this是通过引用捕获的,因此标准不要求存在这样的成员。我做错了什么?

标准在明确方面做得很差,但this只能通过复制捕获。它不可能被左值引用捕获,因为this是C++11§9.3.2/1中的右值。

请注意,该标准禁止通过引用显式捕获this,因为(a)语法不允许在捕获列表中捕获&this,因为this在词汇上是关键字,而不是标识符,以及(b)5.1.2/8禁止在捕获默认值为=时显式捕获this

当捕获默认值为&时,可以隐式捕获this,这似乎是规范中的一个错误,表明它是通过引用捕获的。

我认为您发现了一个规范错误-this是通过引用捕获的,这是正确的,但您在§5.1.2/17中找到的文本仅适用于this是通过复制捕获的。

然而,正如Casey所说,通过引用来捕获this并没有多大意义。

当然,闭包类型中存在这样的数据成员。按值捕获和按引用捕获都需要闭包类型中的数据成员。唯一的问题是它的类型:

T /* maybe const and/or volatile */ * captured_this;

T /* maybe const and/or volatile */ * const & captured_this;

由于this永远不会改变,所以两者之间没有明显的差异。