Entiendo que la forma correcta de capturar this(modificar las propiedades del objeto) en una lambda es la siguiente:
auto f = [this] () { /* ... */ };
Pero tengo curiosidad por la siguiente peculiaridad que he visto:
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;
};
La rareza que me confunde (y me gustaría recibir una respuesta) es por qué funciona lo siguiente:
auto f = [&] () { /* ... */ }; // capture everything by reference
Y por qué no puedo capturar explícitamente thispor referencia:
auto f = [&this] () { /* ... */ }; // a compiler error as seen above.

thisno se puede cambiar, no es lo suficientemente grande para hacer una referencia más rápido ... y de todos modos , en realidad no existe , por lo que ha ninguna vida real, lo que significa que cualquier referencia a ella estaría pendiente por definición.thises un valor pr, no un valor l.Respuestas:
La razón
[&this]no funciona es porque es un error de sintaxis. Cada parámetro separado por comas en ellambda-introduceres uncapture:capture: identifier & identifier thisPuede ver que eso
&thisno está permitido sintácticamente. La razón por la que no está permitido es porque nunca querría capturarthispor referencia, ya que es un pequeño puntero constante. Solo querrá pasarlo por valor, por lo que el lenguaje simplemente no admite la capturathispor referencia.Para capturar
thisexplícitamente, puede usar[this]comolambda-introducer.El primero
capturepuede ser uncapture-defaultque es:capture-default: & =Esto significa capturar automáticamente todo lo que uso, por referencia (
&) o por valor (=) respectivamente, sin embargo, el tratamiento dethises especial, en ambos casos se captura por valor por las razones dadas anteriormente (incluso con una captura predeterminada de&, que generalmente significa capturar por referencia).5.1.2.7/8:
Entonces, lambda actúa como si fuera parte de la función miembro adjunta cuando se usan nombres de miembros (como en su ejemplo, el uso del nombre
x), por lo que generará "usos implícitos" de lathismisma manera que lo hace una función miembro.Así que usted puede utilizar
[this],[&],[=]o[&,this]comolambda-introducerpara capturar elthispuntero por valor.Sin embargo
[&this]y[=, this]están mal formados. En el último caso, gcc advierte con perdón por[=,this]eso enexplicit by-copy capture of ‘this’ redundant with by-copy capture defaultlugar de errores.fuente
[&]si está haciendo algo como crear un bloque para pasarlo a una estructura de control", pero capture explícitamente si está produciendo una lambda que se usará para propósitos menos simples.[&]es una idea horrible si el lambda va a sobrevivir al alcance actual. Sin embargo, muchos usos de lambdas son solo formas de pasar bloques a estructuras de control, y el bloque no sobrevivirá al bloque que se creó en el alcance.thises una palabra clave,thisno es un identificador.Porque estándar no tiene
&thisen las listas de Capturas:N4713 8.4.5.2 Capturas:
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 initializerEntonces, estándar garantiza
thisy*thises válido y&thisno es válido. Además, capturarthissignifica capturar*this(que es un valor, el objeto en sí) por referencia , en lugar de capturar elthispuntero por valor .fuente
*thiscaptura el objeto por valor