C++11 lambda捕获通过声明点的值捕获
C++11 lambda capture by value captures at declaration point
下面的代码打印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;
}
Lambda函数是通过实际将捕获的参数传递给函数来调用的。
在定义lambda的点处value
等于0(并且捕获value
)。由于您是按值进行捕获的,因此捕获后对value
做什么并不重要。
如果您通过引用捕获了value
,那么您将看到打印的1,因为即使捕获点仍然相同(lambda定义),您也将打印捕获对象的当前值,而不是捕获时创建的对象的副本。
是的,捕获是在声明lambda时完成的,而不是在调用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;
}
按预期输出0和1。第一个是按值捕获的,并在捕获点打印值;第二个捕获引用,然后打印其值。
相关文章:
- 在 lambda 捕获中声明的变量的类型推导
- 在类中声明自动 lambda 函数
- 尽管显式声明了返回类型,但对lambda的调用是不明确的
- 为什么我可以在 C++ 的可变 lambda 中捕获未声明的变量
- 使用本地类型声明的G lambda被使用但从未定义 - 确实是一个错误
- 我可以在模板参数中声明一个 constexpr lambda 吗?
- 为什么 c++ lambda 捕获不需要类型声明?
- C++ lambda 按值捕获,而无需更早声明变量
- 如何在C++中声明对 lambda 的引用
- 析构函数在 lambda 捕获说明符中声明的类实例上运行两次
- 如何在声明和定义中拆分静态lambda
- 有没有办法在声明中缩短C 11 lambda签名
- 声明 lambda 时<: 和 :> 是什么意思?
- C++11 lambda捕获通过声明点的值捕获
- 如何将 lambda 的运算符 () 声明为 noreturn?
- 如何用函数指针(不带auto)声明lambda
- C++11是否要求将此lambda声明为可变的
- 所有lambda声明都应该是const-static
- 无法在VS 14 CTP中使用auto声明lambda:类型为'void'的条件表达式是非法的
- 使用 auto 在 C++ 中声明 lambda 变量的首选方法是什么