Siempre me confundo con la captura lambda y no sé si una variable se captura por referencia o por valor. Por ejemplo, si tengo [a] No sé si a se captura por valor o por referencia.

Creo que una forma simple de obtenerlo sería con ejemplos. Entonces, tengamos uno para cada uno de los casos (más si hay más formas de expresar lo mismo):

Capturar:

  • nada
  • todo por referencia
  • todo por valor
  • r1, r2 por referencia. Nada más.
  • v1, v2 por valor. Nada más.
  • r1, r2 por referencia. Descansa por valor.
  • v1, v2 por valor. Descanso por referencia.
  • r1, r2 por referencia, v1, v2 por valor. Nada más.

Ignoremos por completo this ya que es otra bolsa de gusanos.

3
bolov 18 oct. 2017 a las 15:12

3 respuestas

La mejor respuesta
| Capture                                       | Syntax             |
| --------------------------------------------- | ------------------ |
| nothing                                       | []                 |
| all by reference                              | [&]                |
| all by value                                  | [=]                |
| r1, r2 by reference. Nothing else.            | [&r1, &r2]         |
| v1, v2 by value. Nothing else.                | [v1, v2]           |
| r1, r2 by reference. Rest by value.           | [=, &r1, &r2]      |
| v1, v2 by value. Rest by reference.           | [&, v1, v2]        |
| r1, r2 by ref, v1, v2 by value. Nothing else. | [v1, v2, &r1, &r2] |

La regla es simple: precedida por un &, captura por referencia. Solo nombre, captura por valor.

Valores predeterminados: = todo por valor, & todo por referencia. Las cosas para excluir de "todos" usan la regla simple anterior.


Las reglas completas se pueden leer en cppreference.

8
Angew is no longer proud of SO 18 oct. 2017 a las 12:36
  • nada

    []
    
  • todo por referencia

    [&]
    
  • todo por valor

    [=]
    
  • r1, r2 por referencia. Nada más.

    [&r1, &r2]
    
  • v1, v2 por valor. Nada más.

    [v1, v2]
    
  • r1, r2 por referencia. Descansa por valor.

    [=, &r1, &r2]
    
  • v1, v2 por valor. Descanso por referencia.

    [&, v1, v2]
    
  • r1, r2 por referencia, v1, v2 por valor. Nada más.

    [&r1, &r2, v1, v2]
    
3
Garf365 18 oct. 2017 a las 12:53

En resumen:

[]{ }          // do not capture anything
[foo]{ }       // capture `foo` by value
[&foo]{ }      // capture `foo` by reference
[foo, &bar]{ } // capture `foo` by value, `bar` by reference
[=, &foo]{ }   // capture everything by value, `foo` by reference
[&, foo]{ }    // capture everything by reference, `foo` by value

En C ++ 14, también tiene capturas lambda generalizadas :

[i=0]{ }  // create closure with `i` data member initialized to `0`
[i=j]{ }  // create closure with `i` data member initialized to `j`
[i{0}]{ } // create closure with `i` data member initialized to `0`
[i{j}]{ } // create closure with `i` data member initialized to `j`

// create closure with `uptr` data member initialized to `std::move(uptr)`
[uptr = std::move(uptr)]{ } 

// create closure with `foo` reference data member initialized to `something`
[&foo = something]{ }

Si desea capturar condicionalmente por referencia o por valor, puede usar capturas lambda generalizadas para implementar algún tipo de "captura de reenvío perfecto": " captura de objetos perfectamente reenviados en lambdas ".


Ignoremos por completo this ya que es otra bolsa de gusanos.

[this]{ }  // capture `this` by value (the pointer)
[*this]{ } // store a copy of `*this` inside the closure
11
Vittorio Romeo 18 oct. 2017 a las 12:27