下面的代码打印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定义),您将打印捕获对象的当前值,而不是它创建时的副本被捕了.
Joh*_*esD 14
是的,捕获是在声明lambda的时候完成的,而不是在它被调用的时候完成的.将lambda视为一个函数对象,其构造函数将捕获的变量作为参数并将它们分配给相应的成员变量(值或引用,具体取决于捕获模式.)lambda的实际调用没有魔法,它只是一个定期operator()
调用底层函数对象.
在调用点捕获事物没有多大意义 - 如果将lambda作为参数返回或传递给另一个函数并在那里调用,会捕获什么?实际上有一些语言会以这种方式运行 - 如果您x
在函数中引用变量,则假定它在引用时引用x
当前在范围内调用的任何变量.这称为动态范围.大多数语言使用的替代方法,因为它使程序的推理更简单,称为词法范围.
http://en.wikipedia.org/wiki/Lexical_scoping#Lexical_scoping_and_dynamic_scoping
问题是您的打印功能是按值而不是通过引用捕获的.
#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.第一个是按值捕获并在捕获点打印值; 第二个捕获引用,然后打印其值.