[英]Why can't I capture this by-reference ('&this') in lambda?
I understand the correct way to capture this
(to modify object properties) in a lambda is as follows:我了解在 lambda 中捕获
this
的正确方法(修改 object 属性)如下:
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:以及为什么我不能通过引用明确地捕捉
this
:
auto f = [&this] () { /* ... */ }; // a compiler error as seen above.
The reason [&this]
doesn't work is because it is a syntax error. [&this]
不起作用的原因是因为它是语法错误。 Each comma-seperated parameter in the lambda-introducer
is a capture
: lambda-introducer
中的每个逗号分隔参数都是一个capture
:
capture:
identifier
& identifier
this
You can see that &this
isn't allowed syntactically. 您可以看到,
&this
在语法上是不允许的。 The reason it isn't allowed is because you would never want to capture this
by reference, as it is a small const pointer. 这是不允许的原因是因为你绝不会想捕捉
this
引用,因为它是一个小的常量指针。 You would only ever want to pass it by value - so the language just doesn't support capturing this
by reference. 你永远只能希望按值传递它-所以语言只是不支持拍摄
this
作为参考。
To capture this
explicitly you can use [this]
as the lambda-introducer
. 要明确捕获
this
内容,可以使用[this]
作为lambda-introducer
。
The first capture
can be a capture-default
which is: 第一次
capture
可以是capture-default
,即:
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). 这意味着自动捕获我使用的任何东西,分别通过引用(
&
)或通过值( =
)-但是this
的处理是特殊的-在两种情况下,由于先前给出的原因,都通过值捕获(即使默认捕获为&
,通常意味着通过引用捕获)。
5.1.2.7/8: 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.出于名称查找(3.4)的目的,确定
this
(9.3.2)的类型和值,并使用(*this)
(9.3.1)将引用非静态类成员的id表达式转换为类成员访问表达式。 [lambda]的复合语句是在lambda表达式的上下文中考虑的。
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. 所以拉姆达行为,如果它是包围部件功能的一部分(在你的例子一样使用名称的使用,当成员名称
x
),所以它会产生的“隐性习惯” this
就像一个成员函数一样。
If a lambda-capture includes a capture-default that is
&
, the identifiers in the lambda-capture shall not be preceded by&
.如果lambda-capture包含默认为
&
的捕获默认值,则lambda-capture中的标识符不得以&
开头。 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&
.如果lambda-capture包含一个
=
的默认捕获值,则lambda-capture不应包含this
并且其包含的每个标识符均应以&
开头。 An identifier orthis
shall not appear more than once in a lambda-capture.标识符或
this
标识符在lambda捕获中不应出现多次。
So you can use [this]
, [&]
, [=]
or [&,this]
as a lambda-introducer
to capture the this
pointer by value. 因此,您可以将
[this]
, [&]
, [=]
或[&,this]
用作lambda-introducer
以按值捕获this
指针。
However [&this]
and [=, this]
are ill-formed. 但是
[&this]
和[=, this]
格式错误。 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. 在最后一种情况下,gcc宽容地警告
[=,this]
, explicit by-copy capture of 'this' redundant with by-copy capture default
而不是错误。
Because standard doesn't have &this
in Captures lists: 由于标准在“捕获”列表中没有
&this
:
N4713 8.4.5.2 Captures: 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
For the purposes of lambda capture, an expression potentially references local entities as follows:
出于lambda捕获的目的,表达式可能会引用本地实体,如下所示:
7.3 A this expression potentially references *this.
7.3 this表达式可能引用* this。
So, standard guarantees this
and *this
is valid, and &this
is invalid. 因此,标准保证了
this
并且*this
有效,而&this
无效。 Also, capturing this
means capturing *this
(which is a lvalue, the object itself) by reference , rather than capturing this
pointer by value ! 同样,捕获
this
意味着通过引用捕获*this
(这是一个左值,即对象本身), 而不是 通过value捕获this
指针!
I am not sure I understand the question properly, so my answer my not be appropriate in the context of the question.我不确定我是否正确理解了这个问题,所以我的回答在问题的上下文中不合适。
If you want to modify the values in the class in a lambda, then you could:如果要修改 lambda 中 class 中的值,则可以:
class C {
public:
void foo() {
C* this_ptr_2 = this;
auto f = [&this_ptr_2]{
this_ptr_2->x = 69; // Modify a class member.
};
f();
}
private:
int x;
};
Again, I don't know if this answers your question or not.同样,我不知道这是否回答了您的问题。 But if you meant that you wanted to modify class members in a lambda.
但是,如果您的意思是要修改 lambda 中的 class 成员。 I guess the above should suffice.
我想以上应该足够了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.