Как я могу получить доступ к локальным переменным внутри анонимной функции C ++ 11? - PullRequest
29 голосов
/ 18 августа 2011

Я делаю простую нормализацию для вектора (весов), пытаюсь использовать алгоритмы STL, чтобы сделать код максимально чистым (я понимаю, что это довольно тривиально с циклами for):

float tot = std::accumulate(weights.begin(), weights.end(), 0.0);
std::transform(weights.begin(), weights.end(), [](float x)->float{return(x/tot);});

В настоящее время tot не виден анонимной функции, поэтому он не компилируется. Каков наилучший способ сделать локальную переменную видимой для анонимной функции?

Ответы [ 3 ]

47 голосов
/ 18 августа 2011

Вам нужно замыкание.

float tot = std::accumulate(weights.begin(), weights.end(), 0);
std::transform(weights.begin(), weights.end(), [tot](float x)->float{return(x/tot);});

В этом случае tot фиксируется значением.C ++ 11 поддерживает лямбда-выражения:

  1. значение [x]
  2. ссылка [&x]
  3. любая переменная, находящаяся в области действия в настоящее время по ссылке [&]
  4. то же, что и 3, но по значению [=]

Вы можете смешать любое из перечисленного в списке через запятую [x, &y].

8 голосов
/ 18 августа 2011

Лямбда может «захватывать» переменные из окружающего пространства:

[ ..., N, ... ](int a, int b) -> int  { return (a + b) * N; }
 ^^^^^^^^^^^^^  ^^^^^^^^^^^^     ^^^^
 captured vars  local params     ret.type

Вы можете захватить по значению или по ссылке, и вы можете использовать специальный синтаксис [=] и [&], чтобы захватить что угодно из окружающей области, то есть все, что вы фактически используете.

2 голосов
/ 18 августа 2011

Вам необходимо добавить tot в «список захвата»:

float tot = std::accumulate(weights.begin(), weights.end(), 0);
std::transform(weights.begin(), weights.end(), [tot](float x)->float{return(x/tot);});

В качестве альтернативы вы можете использовать захват по умолчанию для захвата tot неявно:

float tot = std::accumulate(weights.begin(), weights.end(), 0);
std::transform(weights.begin(), weights.end(), [=](float x)->float{return(x/tot);});
...