弄清楚为什么在嵌套的 lambda 中通过引用捕获会产生奇怪的结果
Figuring out why capturing by reference in a nested lambda produces a weird result
外层变量x
被值捕获时
return [=](int y){ return x * y; };
foo(2)(3)
产生 6
.
但是,如果我通过引用捕获 x
return [&](int y){ return x * y; };
foo(2)(3)
产生 9
.
最小代码
#include <iostream>
#include <functional>
int main()
{
using namespace std;
function<function<int(int)>(int)> foo = [](int x)
{
return [&](int y) { return x * y; };
};
cout << foo(2)(3);
return 0;
}
问题
我不明白为什么会这样,你能吗?
当 lambda 通过引用捕获 x
时,当 foo(2)
的调用结束时,参数 x
被销毁,然后捕获到它的引用变为悬挂。在 foo(2)(3)
的调用中取消引用会导致 UB,一切皆有可能。
按值捕获不存在此类无效引用问题。
x
是外部函数的本地函数,因此它会在该函数 returns.
后立即被销毁
考虑一个更简单的例子。
#include <iostream>
#include <functional>
int& foo(int x) {
return x;
}
int main()
{
using namespace std;
int& b = foo(5);
return 0;
}
这里更容易看出 b
是悬空引用。
接下来我们继续,我们 return 一个通过引用捕获变量的 lambda,而不是直接 return 引用。
#include <iostream>
#include <functional>
auto foo(int x) {
return [&x]() {return x;};
}
int main()
{
using namespace std;
auto b = foo(5);
return 0;
}
问题依旧。一旦 lambda 被 returned,x
已经超出范围并且不再存在。但是 lambda 持有对它的(悬空)引用。
外层变量x
被值捕获时
return [=](int y){ return x * y; };
foo(2)(3)
产生 6
.
但是,如果我通过引用捕获 x
return [&](int y){ return x * y; };
foo(2)(3)
产生 9
.
最小代码
#include <iostream>
#include <functional>
int main()
{
using namespace std;
function<function<int(int)>(int)> foo = [](int x)
{
return [&](int y) { return x * y; };
};
cout << foo(2)(3);
return 0;
}
问题
我不明白为什么会这样,你能吗?
当 lambda 通过引用捕获 x
时,当 foo(2)
的调用结束时,参数 x
被销毁,然后捕获到它的引用变为悬挂。在 foo(2)(3)
的调用中取消引用会导致 UB,一切皆有可能。
按值捕获不存在此类无效引用问题。
x
是外部函数的本地函数,因此它会在该函数 returns.
考虑一个更简单的例子。
#include <iostream>
#include <functional>
int& foo(int x) {
return x;
}
int main()
{
using namespace std;
int& b = foo(5);
return 0;
}
这里更容易看出 b
是悬空引用。
接下来我们继续,我们 return 一个通过引用捕获变量的 lambda,而不是直接 return 引用。
#include <iostream>
#include <functional>
auto foo(int x) {
return [&x]() {return x;};
}
int main()
{
using namespace std;
auto b = foo(5);
return 0;
}
问题依旧。一旦 lambda 被 returned,x
已经超出范围并且不再存在。但是 lambda 持有对它的(悬空)引用。