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 ?
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-usesthis 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.
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.
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.
Não,
my_huge_vector
não será capturado.[=]
significa que todas as variáveis usadas são capturadas no lambda.fonte
void f() { const int size(10); [] { int x[size]; }; }
. Aqui,size
nã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.)const
coisas não sofrem mutação. a menos que seja uma flag de otimização super agressiva ou OX.