问题
I'm doing a simple normalization on a vector (weights), trying to make use of STL algorithms to make the code as clean as possible (I realize this is pretty trivial with for loops):
float tot = std::accumulate(weights.begin(), weights.end(), 0.0);
std::transform(weights.begin(), weights.end(), [](float x)->float{return(x/tot);});
At present, tot is not visible to the anonymous function, so this doesn't compile. What's the best way of making a local variable visible to the anonymous function?
回答1:
You need a closure.
float tot = std::accumulate(weights.begin(), weights.end(), 0);
std::transform(weights.begin(), weights.end(), [tot](float x)->float{return(x/tot);});
In this case tot
is captured by value. C++11 lambdas support capturing by:
- value
[x]
- reference
[&x]
- any variable currently in scope by reference
[&]
- same as 3, but by value
[=]
You can mix any of the above in a comma separated list [x, &y]
.
回答2:
The lambda can "capture" variables from the ambient scope:
[ ..., N, ... ](int a, int b) -> int { return (a + b) * N; }
^^^^^^^^^^^^^ ^^^^^^^^^^^^ ^^^^
captured vars local params ret.type
You can capture by value or by reference, and you can use the special syntax [=]
and [&]
to capture anything from the ambient scope, i.e. anything you actually end up using.
回答3:
You need to add tot
to the "capture list":
float tot = std::accumulate(weights.begin(), weights.end(), 0);
std::transform(weights.begin(), weights.end(), [tot](float x)->float{return(x/tot);});
Alternatively you can use a capture-default to capture tot
implicitly:
float tot = std::accumulate(weights.begin(), weights.end(), 0);
std::transform(weights.begin(), weights.end(), [=](float x)->float{return(x/tot);});
来源:https://stackoverflow.com/questions/7100889/how-can-i-access-local-variables-from-inside-a-c11-anonymous-function