lambda表达式捕获变量时与函数传参有异曲同工之处,都是开栈并压入形参,形参是实参的一份拷贝
至此,至此形参与实参分道扬镳。形参的生命期与lambda的body或函数的body的作用域一样长的寿命。
而实参与调用者的作用域一样长的寿命。同时形参与实参分布在不同的内存中。保存形参值的内存是
在lambda的body或函数的body对应的栈中。实参值保存在被调用者所在的body对应的栈中。这样的结果是
你在lambda或函数中修改形参根本无法影响到被调用者传递的实际参数的值。欲把lambda或函数内对形参的修改
反应到实参上,对于lambda表达式你捕获实参的引用就好了。对于函数你传递实参的引用或者指针就好
// 存储一个用来计算阶乘的lambda对象
std::function<int(int)> fact = [&fact = fact](int n) -> int {
// &fact = fact 表示左边的fact是右边的fact的别名
// 左边的fact是存在于lambda表达式内部的对象, 生存期与lambda的body生存期一样长
// 右边的fact是存在于lambda表达式外部的对象,生存期与main函数生存期一样长
// 捕获时是引用传递, 相当于 std::function<int(int)>& fact = fact
// 只不过在语法上捕获对象时的定义不那么写, 而是写成 &fact = fact
// return (n < 2) ? 1 : n * fact(n - 1);
int res = 0;
switch (n)
{
case 0: case 1: res = 1; break;
default: res = n * fact(n - 1); break;
}
return res;
};
for (int i = 0; i != 5; ++i)
cout << i << "! = " << fact(i) << "; ";
cout << endl;
// 计算阶乘的和
std::function<int(int)> factsum = [&factsum = factsum, &fact = fact](int n) -> int {
int sum = 0;
switch (n)
{
case 0: sum = 0; break;
case 1: sum = 1; break;
default: sum = factsum(n - 1) + fact(n); break;
}
return sum;
};
for (int i = 0; i != 5; ++i)
{
for (int j = 0; j <= i; ++j)
{
cout << j << "! ";
if (j < i) cout << " + ";
}
cout << " = " << factsum(i) << endl;
}
auto factorial = [](int n) { // 用lambda实现递归
// store a lambda object to emulate "recursive lambda"; aware of extra overhead
std::function<int(int)> fac = [&](int n) -> int {
return (n < 2) ? 1 : n * fac(n - 1);
};
// note that "auto fac = [&](int n){...};" does not work in recursive calls
return fac(n);
};
for (int i{ 5 }; i != 8; ++i) { std::cout << i << "! = " << factorial(i) << "; "; }