Os lambdas do c ++ 11 capturam variáveis ​​que eles não usam?

123

Quando eu uso [=]para indicar que gostaria que todas as variáveis ​​locais fossem capturadas por valor em um lambda, isso resultaria em todas as variáveis ​​locais na função sendo copiadas ou apenas em todas as variáveis ​​locais usadas pelo lambda ?

Então, por exemplo, se eu tiver:

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

O my_huge_vector será copiado, mesmo que eu não o use no lambda?

HighCommander4
fonte

Respostas:

114

Cada variável expressamente nomeada na lista de captura é capturada. A captura padrão captura apenas variáveis ​​que (a) não são expressamente nomeadas na lista de capturas e (b) usadas no corpo da expressão lambda. Se uma variável não for denominada expressamente e você não a usar na expressão lambda, a variável não será capturada. No seu exemplo, my_huge_vectornão é capturado.

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

Se uma expressão lambda tiver um padrão de captura associado e sua instrução composta odr-uses this ou uma variável com duração automática de armazenamento e a entidade odr-used não for explicitamente capturada, então a entidade odr-used é capturada implicitamente.

Sua expressão lambda tem um padrão de captura associado: por padrão, você captura variáveis ​​por valor usando o [=].

Se e somente se uma variável for usada (no sentido da Regra de Uma Definição do termo "usado") é uma variável capturada implicitamente. Como você não usa my_huge_vectorno corpo (a "declaração composta") da expressão lambda, ela não é capturada implicitamente.

Para continuar com §5.1.2 / 14

Uma entidade é capturada por cópia se

  • é capturado implicitamente e o padrão de captura é =ou se
  • é explicitamente capturado com uma captura que não inclui um &.

Como o seu my_huge_vectornão é capturado implicitamente e não é explicitamente capturado, ele não é capturado, por cópia ou por referência.

James McNellis
fonte
10
Você tem uma citação sagrada?
GManNickG
Eu direi, no entanto, que a totalidade do §5.1.2 é importante para entender todos os detalhes. Existem muitos termos técnicos definidos nessa seção e, como as definições dos vários componentes das expressões lambda são necessariamente emaranhadas, é difícil extrair aspas curtas que digam definitivamente "este é X e é por isso que X."
James McNellis
Envie um ping para sua atenção aqui , que diz que essa otimização não é permitida, pelo menos para variáveis ​​nomeadas explicitamente. Não tenho certeza de onde traçar a linha.
GManNickG
@GManNickG: Isso é um ótimo trolling ;-). Foram necessários três cliques nesse link antes que eu percebesse que realmente apontava para esta página ...: -O [De qualquer forma, releremos a especificação do idioma quando entrar no escritório amanhã de manhã e atualizaremos a resposta adequada].
James McNellis
Oh merda, desculpe !!! Minha pergunta foi respondida, eu pretendia vincular aqui . Isso deve ter sido terrivelmente confuso.
GManNickG 4/10/12
16

Não, my_huge_vectornão será capturado. [=]significa que todas as variáveis usadas são capturadas no lambda.

Thomas Minor
fonte
6
Sim. Observe que usado é uma palavra técnica e realmente significa a Regra de Uma Definição usada . Então, por exemplo, considere void f() { const int size(10); [] { int x[size]; }; }. Aqui, sizenão é capturado, mas tudo bem, porque não é usado no sentido de ODR. (O Visual C ++ 2010 não aceita esse código, seja porque as especificações foram alteradas após o lançamento do VC10 ou devido a um bug, presumivelmente isso será corrigido em uma versão futura; o g ++ 4.5.1 o aceita.)
James McNellis
@JamesMcNellis não se preocupe, o MSVC ainda hoje é uma pilha de porcaria fedorenta. cf. godbolt.org/z/vHnnCX (verifique o lulz no gcc). Dito isto; Não entendo por que nenhum identificador exibido em uma expressão avaliada não seria usado por ODR. Eu acho que esse caso definitivamente é usado por ODR, a menos que você queira dizer que poderia ser interpretado como um constexpr, portanto, apenas o valor é útil? Não sei se o compilador assume que as constcoisas não sofrem mutação. a menos que seja uma flag de otimização super agressiva ou OX.
v.oddou 24/05/19