为什么我不能在 lambda 中捕获这个按引用('&this')?
我理解在 lambda 中捕获 this
(以修改对象属性)的正确方法如下:
auto f = [this] () {/* ... */};
但我很好奇我看到的以下特点:
class C {上市:无效的 foo() {//auto f = [] () {//这个没有被捕获auto f = [&] () {//为什么这样做?//auto f = [&this] () {//在'this'之前需要','//auto f = [this] () {//按预期工作x = 5;};F();}私人的:整数 x;};
让我感到困惑(并希望得到回答)的奇怪之处在于以下工作的原因:
auto f = [&] () {/* ... */};//通过引用捕获所有内容
以及为什么我不能通过引用明确捕获this
:
auto f = [&this] () {/* ... */};//如上所示的编译器错误.
解决方案 [&this]
不起作用的原因是因为它是一个语法错误.lambda-introducer
中的每个逗号分隔参数都是一个 capture
:
捕获:标识符&标识符这
您可以看到 &this
在语法上是不允许的.不允许它的原因是因为您永远不想通过引用捕获 this
,因为它是一个小的 const 指针.您只想通过值传递它 - 因此该语言不支持通过引用捕获 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 THE LAMBDA] 在 lambda 表达式的上下文中被考虑.
因此,当使用成员名称时,lambda 就好像它是封闭成员函数的一部分一样(例如在您的示例中使用名称 x
),因此它将生成隐式用法"this
就像成员函数一样.
如果一个 lambda-capture 包含一个默认的 capture-default,即 &
,则 lambda-capture 中的标识符不应是前面是 &
.如果 lambda 捕获包含 =
的捕获默认值,则 lambda 捕获不应包含this
及其包含的每个标识符都应以 &
开头.标识符或 this
出现的次数不得超过一次在 lambda 捕获中.
所以你可以使用 [this]
、[&]
、[=]
或 [&,this]
作为 lambda-introducer
以按值捕获 this
指针.
然而,[&this]
和 [=, this]
是格式错误的.在最后一种情况下,gcc 宽容地警告 [=,this]
,显式按副本捕获'this'冗余,默认按副本捕获
,而不是错误.>
I understand the correct way to capture this
(to modify object properties) in a lambda is as follows:
auto f = [this] () { /* ... */ };
But I'm curious as to the following peculiarity I've seen:
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;
};
The oddity that I am confused by (and would like answered) is why the following works:
auto f = [&] () { /* ... */ }; // capture everything by reference
And why I cannot explicitly capture this
by reference:
auto f = [&this] () { /* ... */ }; // a compiler error as seen above.
解决方案
The reason [&this]
doesn't work is because it is a syntax error. Each comma-seperated parameter in the lambda-introducer
is a capture
:
capture:
identifier
& identifier
this
You can see that &this
isn't allowed syntactically. The reason it isn't allowed is because you would never want to capture this
by reference, as it is a small const pointer. You would only ever want to pass it by value - so the language just doesn't support capturing this
by reference.
To capture this
explicitly you can use [this]
as the lambda-introducer
.
The first capture
can be a capture-default
which is:
capture-default:
&
=
This means capture automatically whatever I use, by reference (&
) or by value (=
) respectively - however the treatment of this
is special - in both cases it is captured by value for the reasons given previously (even with a default capture of &
, which usually means capture by reference).
5.1.2.7/8:
For purposes of name lookup (3.4), determining the type and value of
this
(9.3.2) and transforming id- expressions referring to non-static class members into class member access expressions using(*this)
(9.3.1), the compound-statement [OF THE LAMBDA] is considered in the context of the lambda-expression.
So the lambda acts as if it is part of the enclosing member function when using member names (like in your example the use of the name x
), so it will generate "implicit usages" of this
just like a member function does.
If a lambda-capture includes a capture-default that is
&
, the identifiers in the lambda-capture shall not be preceded by&
. If a lambda-capture includes a capture-default that is=
, the lambda-capture shall not containthis
and each identifier it contains shall be preceded by&
. An identifier orthis
shall not appear more than once in a lambda-capture.
So you can use [this]
, [&]
, [=]
or [&,this]
as a lambda-introducer
to capture the this
pointer by value.
However [&this]
and [=, this]
are ill-formed. In the last case gcc forgivingly warns for [=,this]
that explicit by-copy capture of ‘this’ redundant with by-copy capture default
rather than errors.
相关文章