¿C ++ 11 lambdas capturan variables que no usan?

124

Cuando uso [=]para indicar que me gustaría que todas las variables locales sean capturadas por valor en una lambda, ¿eso dará como resultado que se copien todas las variables locales en la función, o solo todas las variables locales que son utilizadas por la lambda ?

Entonces, por ejemplo, si tengo:

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

¿Se copiará my_huge_vector, aunque no lo use en lambda?

HighCommander4
fuente

Respuestas:

115

Se captura cada variable nombrada expresamente en la lista de captura. La captura predeterminada solo capturará variables que son (a) no nombradas expresamente en la lista de captura y (b) utilizadas en el cuerpo de la expresión lambda. Si una variable no tiene un nombre expreso y no usa la variable en la expresión lambda, entonces la variable no se captura. En su ejemplo, my_huge_vectorno se captura.

Según C ++ 11 §5.1.2 [expr.prim.lambda] / 11:

Si una expresión lambda tiene un valor predeterminado de captura asociado y su enunciado compuesto odr-uses this o una variable con duración de almacenamiento automática y la entidad odr-used no se captura explícitamente, entonces se dice que la entidad odr-used se captura implícitamente.

Su expresión lambda tiene un valor predeterminado de captura asociado: de forma predeterminada, captura variables por valor utilizando [=].

Si y solo si se usa una variable (en el sentido de la regla de una definición del término "usado") es una variable capturada implícitamente. Como no se usa my_huge_vectoren absoluto en el cuerpo (la "declaración compuesta") de la expresión lambda, no se captura implícitamente.

Para continuar con §5.1.2 / 14

Una entidad es capturada por copia si

  • se captura implícitamente y el valor predeterminado de captura es =o si
  • se captura explícitamente con una captura que no incluye un &.

Como su my_huge_vectorno se captura implícitamente y no se captura explícitamente, no se captura en absoluto, por copia o por referencia.

James McNellis
fuente
10
¿Tienes una cita sagrada?
GManNickG
Sin embargo, diré que la totalidad de §5.1.2 es importante para comprender todos los detalles. Hay muchos términos técnicos definidos en esa sección y debido a que las definiciones de los diversos componentes de las expresiones lambda están necesariamente enredadas, es difícil extraer citas cortas que definitivamente digan "esto es X y es por eso que X".
James McNellis
Haga ping a su atención aquí , que dice que tal optimización no está permitida, al menos para variables explícitamente nombradas. No estoy seguro de dónde dibujar la línea.
GManNickG
@GManNickG: Ese es un buen curricán muy bueno ;-). Me tomó unos tres clics de ese enlace antes de darme cuenta de que en realidad apuntaba a esta página ...: -O [En cualquier caso, volveré a leer las especificaciones del idioma cuando llegue a la oficina mañana por la mañana y actualice la respuesta apropiadamente.]
James McNellis
Oh mierda, lo siento !!! Mi pregunta fue respondida, tenía la intención de vincular aquí en su lugar. Eso debe haber sido terriblemente confuso.
GManNickG
16

No, my_huge_vectorno será capturado. [=]significa que todas las variables utilizadas se capturan en la lambda.

Thomas Minor
fuente
66
Sí. Sin embargo, tenga en cuenta que usado es una palabra técnica, y realmente significa la regla de una definición utilizada . Entonces, por ejemplo, considere void f() { const int size(10); [] { int x[size]; }; }. Aquí, sizeno se captura, pero está bien porque no se usa en el sentido ODR. (Visual C ++ 2010 no acepta este código, ya sea porque la especificación cambió después del lanzamiento de VC10 o debido a un error, presumiblemente esto se solucionará en una próxima versión; g ++ 4.5.1 lo acepta.)
James McNellis
@JamesMcNellis no se preocupe, MSVC sigue siendo un montón de basura maloliente hoy. cf. godbolt.org/z/vHnnCX (verifique en gcc para lulz). Dicho eso No entiendo por qué ningún identificador que aparece en una expresión evaluada no se usaría ODR. Creo que este caso definitivamente se usa ODR a menos que quiera decir que podría interpretarse como un constexpr, por lo tanto, ¿solo el valor es útil? No estoy seguro de que el compilador asuma que las constcosas no mutan potencialmente. a menos que sea una bandera de optimización súper agresiva OX o cosas así
v.oddou