Version tl;dr en bas de page.
§5.1.2 [expr.prim.lambda]
p1 expression lambda :
lambda-introducteur lambda-déclarateur opt énoncé composé
p3 Le type de expression lambda (qui est aussi le type de l'objet de fermeture) est un type de classe unique, sans nom, non syndiqué - appelé le type de fermeture - dont les propriétés sont décrites ci-dessous. Cette catégorie de classe n'est pas un agrégat (8.5.1). Le type de fermeture est déclaré dans la plus petite portée de bloc, de classe ou d'espace de nom qui contient le type de fermeture correspondant. expression lambda . ( Ma note : les fonctions ont une portée de bloc. )
p5 Le type de fermeture pour un expression lambda a un public inline
fonction appel opérateur [...]
p7 Le expression lambda 's énoncé composé donne le fonction-corps (8.4) de l'opérateur d'appel de fonction [...]
Puisque l'instruction composée est directement prise comme corps de l'opérateur d'appel de fonction, et que le type de fermeture est défini dans la plus petite portée (la plus interne), cela revient à écrire ce qui suit :
void some_function()
{
struct /*unnamed unique*/{
inline void operator()(int const& i) const{
static int calls_to_cout = 0;
cout << "cout has been called " << calls_to_cout << " times.\n"
<< "\tCurrent int: " << i << "\n";
++calls_to_cout;
}
} lambda;
std::vector<int> v = {0,1,2,3,4,5};
std::for_each( v.begin(), v.end(), lambda);
}
Ce qui est légal en C++, les fonctions sont autorisées à avoir static
les variables locales.
§3.7.1 [basic.stc.static]
p1 Toutes les variables qui n'ont pas de durée de stockage dynamique, qui n'ont pas de durée de stockage par fil et qui ne sont pas locales ont une durée de stockage statique. Le stockage de ces entités durera toute la durée du programme. .
p3 Le mot-clé static
peut être utilisé pour déclarer une variable locale avec une durée de stockage statique. [...]
§6.7 [stmt.dcl] p4
(Ceci traite de l'initialisation des variables avec une durée de stockage statique dans une portée de bloc).
[...] Sinon, une telle variable est initialisée la première fois que le contrôle passe par sa déclaration ; [...]
Je le répète :
- Le type d'une expression lambda est créé dans la portée la plus interne.
- Il est no créé à nouveau pour chaque appel de fonction (cela n'aurait pas de sens, puisque le corps de la fonction englobante serait comme mon exemple ci-dessus).
- Il obéit à (presque) toutes les règles des classes et des structures normales (juste quelques trucs à propos de
this
est différent), puisqu'il es une catégorie de classe non syndiquée.
Maintenant que nous nous sommes assurés que pour chaque appel de fonction, le type de fermeture est le même, nous pouvons dire sans risque que la variable locale statique est également la même ; elle est initialisée la première fois que l'opérateur d'appel de fonction est invoqué et vit jusqu'à la fin du programme.
3 votes
Si je comprends bien votre question, il vous manque probablement une
calls_to_cout++
quelque part.1 votes
Lambdageek : oh oui, bien vu :) thinko. Pourquoi le compilateur ne serait-il pas capable de le déduire ? Ne serait-ce pas quelque chose de cool :)
0 votes
C'est à tout le moins une très mauvaise pratique. Ainsi, indépendamment de ce que dit la norme, je m'abstiendrais d'utiliser cette (oui, je suis de l'Union européenne). Singleton considéré comme nuisible fraction).
0 votes
Mon intuition me dit que oui, puisqu'une seule version de ce lambda sera compilée au moment de la compilation, et que tout élément statique ne sera initialisé qu'une seule fois, mais je n'en ferais pas ma réponse officielle ;)
0 votes
Extrait de 5.2 : "L'évaluation d'une expression lambda donne lieu à un objet de fermeture [...], dont le type est un type unique et non nommé [...]." Je dirais donc qu'à chaque fois que l'expression est rencontrée, on obtient un objet de fermeture [...]. nouveau type.
2 votes
Au fait, en passant par
const int&
est totalement inutile. Une référence nécessite même probablement plus de mémoire qu'uneint
.0 votes
@PaulManta : exemple simplifié à l'extrême d'une chose plus compliquée.
0 votes
En fait, cette question n'a rien à voir avec les lambdas. On peut se poser la même question pour toute classe locale dont la fonction membre contient une variable statique.