Ce qui se passe
Le premier ne modifiera que sa propre copie de x
et laisser l'extérieur x
inchangé. La seconde modifiera le à l'extérieur de x
.
Ajoutez une déclaration d'impression après avoir essayé chacune d'elles :
a();
std::cout << x << "----\n";
b();
std::cout << x << '\n';
Il est prévu de l'imprimer :
6
5
----
6
6
Pourquoi
Il peut être utile de considérer que lambda
[...] Les expressions fournissent un moyen concis de créer des objets fonctionnels simples.
(voir [expr.prim.lambda] de la norme)
Ils ont
[...] un opérateur public d'appel de fonction inline [...]
qui est déclaré comme un const
mais seulement
[...] si et seulement si l'expression lambda clause de déclaration des paramètres n'est pas suivi par mutable
Vous pouvez penser à comme 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;
Q : Mais si c'est un const
pourquoi je peux encore modifier x
?
A : Vous ne faites que changer l'extérieur x
. Le propre lambda x
est une référence, et l'opération ++x
ne modifie pas la référence mais la valeur référencée .
Cela fonctionne parce qu'en C++, la constance d'un pointeur/référence ne change pas la constance de la pointe/référence vue à travers lui.