Подтвердить что ты не робот

С++ 11 лямбда-захват по значениям в точке объявления

Нижеприведенный код печатает 0, но я ожидаю увидеть 1. Мой вывод состоит в том, что функции лямбда не вызывают, фактически передавая захваченные параметры в функции, что более интуитивно. Я прав, или я чего-то не хватает?

#include <iostream>
int main(int argc, char **argv){
  int value = 0;
  auto incr_value  = [&value]() { value++; };
  auto print_value = [ value]() { std::cout << value << std::endl; };
  incr_value();
  print_value();
  return 0;
}
4b9b3361

Ответ 1

Лямбда-функции -, вызываемые фактической передачей захваченных параметров функции.

value равно 0 в точке, где определяется лямбда (и value). Поскольку вы захватываете по значению, не имеет значения, что вы делаете с value после захвата.

Если вы взяли value по ссылке, то вы увидите 1 напечатанную, так как хотя точка захвата остается неизменной (определение лямбда), вы будете печатать текущее значение захваченного объекта, а не его копия была создана при ее захвате.

Ответ 2

Да, захваты выполняются в точке, обозначенной лямбдой, а не при ее вызове. Подумайте о лямбде как объекте функции, конструктор которого принимает захваченные переменные в качестве параметров и присваивает их соответствующим переменным-членам (значения или ссылки в зависимости от режима захвата). Фактический вызов лямбды не имеет магии, это просто регулярный вызов operator() основного объекта функции.

Захват вещей в точке вызова не имеет большого смысла - что было бы захвачено, если лямбда была возвращена или передана как параметр другой функции и называется там? На самом деле существуют языки, которые ведут себя таким образом - если вы ссылаетесь на переменную x в функции, предполагается, что она относится к любой переменной с именем x, находящейся в настоящее время в области в точке вызова. Это называется динамическим охватом. Альтернатива, используемая большинством языков, потому что упрощает рассуждение о программах, называется лексическим охватом.

http://en.wikipedia.org/wiki/Lexical_scoping#Lexical_scoping_and_dynamic_scoping

Ответ 3

Проблема заключается в том, что ваша функция печати захватывается по значению, а не по ссылке.

#include <iostream>
int main(int argc, char **argv){
  int value = 0;
  auto incr_value  = [&value]() { value++; };
  auto print_value = [ value]() { std::cout << value << std::endl; };
  auto print_valueref = [ &value]() { std::cout << value << std::endl; };

  incr_value();
  print_value();
  print_valueref();
  return 0;
}

Вывод 0 и 1, как ожидалось. Первый захвачен значением и печатает значение в точке захвата; второй фиксирует ссылку, а затем печатает ее значение.