funciones - lambda examples c++
C++ Lambdas: diferencia entre "mutable" y captura por referencia (1)
En C ++ puedes declarar lambdas por ejemplo así:
int x = 5;
auto a = [=]() mutable { ++x; std::cout << x << ''/n''; };
auto b = [&]() { ++x; std::cout << x << ''/n''; };
Ambos me permiten modificar x
, ¿cuál es la diferencia?
Que esta pasando
El primero solo modificará su propia copia de x
y dejará el exterior x
sin cambios. El segundo modificará el exterior x
.
Agregue una declaración de impresión después de probar cada uno:
a();
std::cout << x << "----/n";
b();
std::cout << x << ''/n'';
Se espera que esto se imprima:
6
5
----
6
6
Por qué
Puede ser útil considerar que las [...] expressions provide a concise way to create simple function objects
lambda [...] expressions provide a concise way to create simple function objects
(vea [expr.prim.lambda] del Estándar).
Tienen un operador de llamada de función pública [...] en línea que se declara como una función const
, [...] pero solo si y solo si la cláusula parameter-declaration-clause
lambdaexpression no es seguida por mutable
(texto en cursiva = citas del estándar).
Puedes pensar como si
int x = 5;
auto a = [=]() mutable { ++x; std::cout << x << ''/n''; };
==>
int x = 5;
class __lambda_a {
int x;
public:
__lambda_a () : x($lookup-one-outer$::x) {}
inline void operator() { ++x; std::cout << x << ''/n''; }
} a;
y
auto b = [&]() { ++x; std::cout << x << ''/n''; };
==>
int x = 5;
class __lambda_b {
int &x;
public:
__lambda_b() : x($lookup-one-outer$::x) {}
inline void operator() const { ++x; std::cout << x << ''/n''; }
// ^^^^^
} b;
P: Pero si es una función const
, ¿por qué aún puedo cambiar x
?
A: solo estás cambiando el exterior x
. La propia x
lambda es una referencia, y la operación ++x
no modifica la referencia , sino el valor referido .
Esto funciona porque en C ++, la constness de un puntero / referencia no cambia la constness del pointee / referencee visto a través de él.