C++ 11 lambda按值捕获在声明点捕获

per*_*eal 31 c++ lambda c++11

下面的代码打印0,但我希望看到1.我的结论是lambda函数不是通过实际将捕获的参数传递给函数来调用的,这更直观.我是对的还是我错过了什么?

#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;
}
Run Code Online (Sandbox Code Playgroud)

Fer*_*cio 29

通过将捕获的参数实际传递给函数调用Lambda 函数.

value在定义lambda(并被value捕获)的点处等于0 .由于您是按值捕获的,因此value捕获后您执行的操作无关紧要.

如果您value通过引用捕获,那么您将看到1打印,因为即使捕获点仍然相同(lambda定义),您将打印捕获对象的当前值,而不是它创建时的副本被捕了.

  • 这里可能有误导的是措辞:按价值意味着"生成副本".lambda有一个变量的副本,它是在lambda声明时获取的值.由于lambda具有私有副本,因此不会在lambda中修改或读取原始对象.这就是为什么实际上存在引用捕获的原因,以允许您想要查看/修改原始的情况. (6认同)

Joh*_*esD 14

是的,捕获是在声明lambda的时候完成的,而不是在它被调用的时候完成的.将lambda视为一个函数对象,其构造函数将捕获的变量作为参数并将它们分配给相应的成员变量(值或引用,具体取决于捕获模式.)lambda的实际调用没有魔法,它只是一个定期operator()调用底层函数对象.

在调用点捕获事物没有多大意义 - 如果将lambda作为参数返回或传递给另一个函数并在那里调用,会捕获什么?实际上有一些语言会以这种方式运行 - 如果您x在函数中引用变量,则假定它在引用时引用x当前在范围内调用的任何变量.这称为动态范围.大多数语言使用的替代方法,因为它使程序的推理更简单,称为词法范围.

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


VSO*_*low 5

问题是您的打印功能是按值而不是通过引用捕获的.

#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;
}
Run Code Online (Sandbox Code Playgroud)

按预期输出0和1.第一个是按值捕获并在捕获点打印值; 第二个捕获引用,然后打印其值.