int n;
int main()
{
[](){ n = 0; }(); // clang says "ok"
int m;
[](){ m = 0; }(); // clang says "not ok"
}
Je me demande seulement:
Si le lambda ne capture rien, est-il autorisé à accéder aux variables globales selon la norme C++?
Oui bien sûr. Les règles de recherche de nom normales s'appliquent.
[expr.prim.lambda]/7 ... à des fins de recherche de nom ... l'instruction instruction composée est considérée dans le contexte de l'expression expression-lambda .
Re: pourquoi les variables locales sont traitées différemment des variables globales.
[expr.prim.lambda]/13 ... Si un expression-lambda ou une instanciation du modèle d'opérateur d'appel de fonction d'un lambda générique odr-uses (3.2)
this
ou une variable avec une durée de stockage automatique à partir de sa portée, cette entité doit être capturée par expression lambda.[expr.prim.lambda]/9 A expression-lambda dont la plus petite portée englobante est une portée de bloc (3.3.3) est une expression lambda locale... Le scope} d'une expression lambda locale est l'ensemble des étendues englobantes jusqu'à et y compris la fonction englobante la plus interne et ses paramètres.
Dans votre exemple, m
est une variable avec une durée de stockage automatique à partir de la portée de lambda et doit donc être capturée. n
n'est pas, et n'a donc pas à l'être.
En fait, la [](){ n = 10; }();
ne capture rien, il utilise plutôt la variable globale.
int n;
int main()
{
[](){ n = 10; }(); // clang says "ok"
std::cout << n; // output 10
}
Voir capture-list dans Explaination
capture-list - une liste de zéro ou plusieurs captures séparées par des virgules, commençant éventuellement par une capture-default.
La liste de capture peut être passée comme suit (voir ci-dessous la description détaillée ):
- [a, & b] où a est capturé par copie et b est capturé par référence.
- [this] capture l'objet actuel (* this) par référence
- [&] capture toutes les variables automatiques utilisées dans le corps du lambda par référence et l'objet actuel par référence s'il existe
- [=] capture toutes les variables automatiques utilisées dans le corps du lambda par copie et l'objet actuel par référence s'il existe
- [] ne capture rien
Les variables globales, statiques et const sont accessibles par défaut:
#include <iostream>
int n;
int main()
{
[](){ n = 10; }();
std::cout << n << std::endl;
static int m = 1;
[](){ m = 100; }();
std::cout << m << std::endl;
const int l = 200;
[](){ std::cout << l << std::endl; }();
}