I lambda c ++ 11 catturano le variabili che non usano?


124

Quando uso [=]per indicare che desidero che tutte le variabili locali vengano catturate per valore in un lambda, ciò comporterà la copia di tutte le variabili locali nella funzione o solo di tutte le variabili locali utilizzate da lambda ?

Quindi, ad esempio, se ho:

vector<int> my_huge_vector(100000);
int my_measly_int;
some_function([=](int i){ return my_measly_int + i; });

My_huge_vector verrà copiato, anche se non lo uso in lambda?

Risposte:


115

Ogni variabile espressamente denominata nell'elenco di cattura viene acquisita. L'acquisizione predefinita acquisirà solo le variabili che sono (a) non espressamente denominate nell'elenco di acquisizione e (b) utilizzate nel corpo dell'espressione lambda. Se una variabile non è espressamente denominata e non si utilizza la variabile nell'espressione lambda, la variabile non viene acquisita. Nel tuo esempio, my_huge_vectornon viene catturato.

Per C ++ 11 §5.1.2 [expr.prim.lambda] / 11:

Se un'espressione lambda ha un'impostazione predefinita di acquisizione associata e la sua istruzione composta odr-usa this o una variabile con durata di archiviazione automatica e l' entità usata da odr non viene catturata in modo esplicito, si dice che l' entità usata da odr sia catturata implicitamente.

La tua espressione lambda ha un'acquisizione predefinita associata: per impostazione predefinita, acquisisci le variabili in base al valore utilizzando il [=].

Se e solo se una variabile viene utilizzata (nel senso di una regola di definizione del termine "usata") viene catturata implicitamente. Poiché non si utilizza my_huge_vectoraffatto nel corpo ("l'istruzione composta") dell'espressione lambda, non viene catturata in modo implicito.

Per continuare con §5.1.2 / 14

Un'entità viene catturata dalla copia se

  • viene catturato in modo implicito e il valore predefinito di cattura è =o if
  • viene acquisito in modo esplicito con un'acquisizione che non include un file &.

Poiché il tuo my_huge_vectornon viene catturato implicitamente e non viene catturato esplicitamente, non viene catturato affatto, per copia o per riferimento.


10
Hai una citazione sacra?
GManNickG

Dirò, tuttavia, che la totalità del §5.1.2 è importante per comprendere tutti i dettagli. Ci sono molti termini tecnici definiti in quella sezione e poiché le definizioni dei vari componenti delle espressioni lambda sono necessariamente intrecciate, è difficile tirare fuori virgolette brevi che dicano definitivamente "questo è X e questo è il motivo per X".
James McNellis

Ping per la tua attenzione qui , che dice che tale ottimizzazione non è consentita, almeno per le variabili denominate esplicitamente. Non sono sicuro di dove tracciare la linea.
GManNickG

@GManNickG: Questo è un ottimo trolling ;-). Mi ci sono voluti tre buoni clic su quel collegamento prima di rendermi conto che in realtà puntava a questa pagina ...: -O [In ogni caso, rileggerò le specifiche della lingua quando entro in ufficio domani mattina e aggiornerò la risposta in modo appropriato.]
James McNellis

Oh merda, scusa !!! La mia domanda ha avuto risposta, volevo invece collegarmi qui . Deve essere stato terribilmente confuso.
GManNickG

16

No, my_huge_vectornon verrà catturato. [=]significa che tutte le variabili utilizzate vengono acquisite in lambda.


6
Sì. Nota che usato è una parola tecnica, però, e in realtà significa una regola di definizione usata . Quindi, ad esempio, considera void f() { const int size(10); [] { int x[size]; }; }. Qui, sizenon viene catturato ma va bene perché non viene utilizzato nel senso ODR. (Visual C ++ 2010 non accetta questo codice, o perché le specifiche sono cambiate dopo il rilascio di VC10 oa causa di un bug, presumibilmente verrà risolto in una versione imminente; g ++ 4.5.1 lo accetta.)
James McNellis

@JamesMcNellis dp non preoccuparti, MSVC è ancora un mucchio di merda puzzolente oggi. cf. godbolt.org/z/vHnnCX (controlla in gcc per il lulz). Detto ciò; Non capisco perché qualsiasi identificatore che appare in un'espressione valutata non sarebbe utilizzato da ODR. Penso che questo caso sia sicuramente utilizzato da ODR a meno che tu non intenda che potrebbe essere interpretato come un constexpr quindi solo il valore è utile? Non sono sicuro che il compilatore presuma che le constcose non cambino potenzialmente. a meno che forse l'ottimizzazione super aggressiva non contrassegni OX o altro.
v.oddou
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.