Les lambdas C ++ 11 capturent-ils les variables qu'ils n'utilisent pas?
124
Lorsque j'utilise [=]pour indiquer que je voudrais que toutes les variables locales soient capturées par valeur dans un lambda, cela entraînera-t-il la copie de toutes les variables locales de la fonction ou simplement de toutes les variables locales utilisées par le lambda ?
Chaque variable expressément nommée dans la liste de capture est capturée. La capture par défaut ne capturera que les variables qui sont à la fois (a) non expressément nommées dans la liste de capture et (b) utilisées dans le corps de l'expression lambda. Si une variable n'est pas expressément nommée et que vous n'utilisez pas la variable dans l'expression lambda, la variable n'est pas capturée. Dans votre exemple, my_huge_vectorn'est pas capturé.
Selon C ++ 11 §5.1.2 [expr.prim.lambda] / 11:
Si une expression lambda a une capture par défaut associée et son instruction composée odr-usesthis ou une variable avec une durée de stockage automatique et que l' entité utilisée par odr n'est pas explicitement capturée, alors l' entité utilisée par odr est dite implicitement capturée.
Votre expression lambda est associée à une capture par défaut: par défaut, vous capturez des variables par valeur à l'aide de [=].
Si et seulement si une variable est utilisée (dans le sens d'une règle de définition unique du terme «utilisé») est une variable capturée implicitement. Puisque vous n'utilisez pas my_huge_vectordu tout dans le corps (l '"instruction composée") de l'expression lambda, elle n'est pas capturée implicitement.
Pour continuer avec §5.1.2 / 14
Une entité est capturée par copie si
il est implicitement capturé et la capture par défaut est =ou si
il est explicitement capturé avec une capture qui n'inclut pas de fichier &.
Puisque votre my_huge_vectorn'est pas capturé implicitement et qu'il n'est pas explicitement capturé, il n'est pas du tout capturé, par copie ou par référence.
Je dirai cependant que l'intégralité du §5.1.2 est importante pour comprendre tous les détails. Il y a beaucoup de termes techniques définis dans cette section et parce que les définitions des différents composants des expressions lambda sont nécessairement intriquées, il est difficile de sortir de courtes citations qui disent définitivement "c'est X et c'est pourquoi X".
James McNellis
Ping à votre attention ici , qui dit qu'une telle optimisation n'est pas autorisée, du moins pour les variables explicitement nommées. Je ne sais pas où tracer la ligne.
GManNickG
@GManNickG: C'est un très bon trolling ;-). Il m'a fallu trois bons clics sur ce lien avant de me rendre compte qu'il pointait réellement vers cette page ...: -O [Dans tous les cas, je relirai les spécifications de la langue quand j'arriverai au bureau demain matin et je mettrai à jour la réponse appropriée.]
James McNellis
Oh merde, désolé !!! Ma question a été répondue, je voulais plutôt créer un lien ici . Cela a dû être terriblement déroutant.
GManNickG
16
Non, my_huge_vectorne sera pas capturé. [=]signifie que toutes les variables utilisées sont capturées dans le lambda.
Oui. Notez que utilisé est un mot technique, cependant, et signifie vraiment la règle d'une définition utilisée . Alors, par exemple, considérez void f() { const int size(10); [] { int x[size]; }; }. Ici, ce sizen'est pas capturé mais c'est correct car il n'est pas utilisé dans le sens ODR. (Visual C ++ 2010 n'accepte pas ce code, soit parce que la spécification a changé après la publication de VC10, soit en raison d'un bogue, cela sera vraisemblablement corrigé dans une prochaine version; g ++ 4.5.1 l'accepte.)
James McNellis
@JamesMcNellis ne vous inquiétez pas, MSVC est toujours un tas de merde puante aujourd'hui. cf. godbolt.org/z/vHnnCX (vérifiez dans gcc pour le lulz). Cela dit; Je ne comprends pas pourquoi un identifiant apparaissant dans une expression évaluée ne serait pas utilisé par ODR. Je pense que ce cas est définitivement utilisé par ODR à moins que vous ne vouliez dire qu'il pourrait être interprété comme une constexpr, donc seule la valeur est utile? Je ne suis pas sûr que le compilateur suppose que les constchoses ne mutent pas potentiellement. sauf peut-être un drapeau d'optimisation super agressif OX ou des trucs.
Non,
my_huge_vector
ne sera pas capturé.[=]
signifie que toutes les variables utilisées sont capturées dans le lambda.la source
void f() { const int size(10); [] { int x[size]; }; }
. Ici, cesize
n'est pas capturé mais c'est correct car il n'est pas utilisé dans le sens ODR. (Visual C ++ 2010 n'accepte pas ce code, soit parce que la spécification a changé après la publication de VC10, soit en raison d'un bogue, cela sera vraisemblablement corrigé dans une prochaine version; g ++ 4.5.1 l'accepte.)const
choses ne mutent pas potentiellement. sauf peut-être un drapeau d'optimisation super agressif OX ou des trucs.