Почему я не могу захватить это по ссылке ('&this') в лямбда?
Я понимаю, правильный способ захвата this
(для изменения свойств объекта) в лямбде выглядит следующим образом:
auto f = [this] () { /* ... */ };
но мне любопытно, что я видел следующую особенность:
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;
};
странность, что я смущен (и хотел бы ответить), почему следующие работы:
auto f = [&] () { /* ... */ }; // capture everything by reference
и почему я не могу четко улавливать this
ссылки:
auto f = [&this] () { /* ... */ }; // a compiler error as seen above.
2 ответа:
причина
[&this]
не работает, потому что это синтаксическая ошибка. Каждый разделенный запятыми параметр вlambda-introducer
- этоcapture
:capture: identifier & identifier this
видно, что
&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), составное утверждение [лямбды] рассматривается в контексте лямбда-выражения.таким образом, лямбда действует так, как будто она является частью функции-члена enclosing при использовании имена членов (как в вашем примере использование имени
x
), поэтому он будет генерировать "неявные использования"this
так же, как это делает функция-член.если лямбда-захват включает в себя захват-значение по умолчанию, которое
&
, идентификаторы в лямбда-захвате не должны быть предшествует&
. Если лямбда-захват включает в себя захват-значение по умолчанию, которое=
лямбда-захват не должен содержатьthis
и каждый идентификатор, который он содержит, должен предшествовать&
. Идентификатор илиthis
не должно появляться более попав в лямбда-захват.так что вы можете использовать
[this]
,[&]
,[=]
или[&,this]
какlambda-introducer
захватthis
указатель на значение.[&this]
и[=, this]
плохо сформированы. В последнем случае gcc прощающе предупреждает за[=,this]
этоexplicit by-copy capture of ‘this’ redundant with by-copy capture default
, а не ошибки.
потому что стандарт не имеет
&this
в списках захватов: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
для целей лямбда-захвата выражение потенциально ссылается на локальные сущности следующим образом:
7.3 A это выражение потенциально ссылается на * this.
Итак, стандартные гарантии
this
и*this
и&this
является недействительным. Кроме того, захватthis
использование*this
(что является lvalue, сам объект)по ссылке,, а не захватthis
указатель по стоимости!