web-dev-qa-db-fra.com

Un lambda ne capturant rien peut-il accéder aux variables globales?

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++?

15
xmllmx

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.

15
Igor Tandetnik

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
8
Jiahao Cai

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; }();
}
1
Soumya Kanti