弄清楚为什么在嵌套 lambda 中通过引用捕获会产生奇怪的结果

xpo*_*ort 5 c++ lambda

当外部变量x被值捕获时

return [=](int y){ return x * y; };
Run Code Online (Sandbox Code Playgroud)

foo(2)(3)产生6.

但是如果我x通过引用捕获

return [&](int y){ return x * y; };
Run Code Online (Sandbox Code Playgroud)

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

问题

我不明白为什么会发生这种情况,你能吗?

sup*_*per 9

x是外部函数的本地函数,因此一旦该函数返回,它就会被销毁。

考虑一个更简单的例子。

#include <iostream>
#include <functional>

int& foo(int x) {
    return x;
}

int main()
{
    using namespace std;
    int& b = foo(5);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在这里更容易看出这b是一个悬空引用。

接下来,我们不直接返回引用,而是返回一个通过引用捕获变量的 lambda。

#include <iostream>
#include <functional>

auto foo(int x) {
    return [&x]() {return x;};
}

int main()
{
    using namespace std;
    auto b = foo(5);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

问题仍然存在。一旦 lambda 返回,x它就已经超出范围并且不再存在。但 lambda 持有对其的(悬空)引用。


son*_*yao 6

当 lambdax通过引用捕获时,当 的调用结束时foo(2),参数x将被销毁,然后捕获到它的引用将变为悬空。在调用中对它的取消引用foo(2)(3)导致 UB,一切皆有可能。

按值捕获不存在此类无效引用问题。

  • @user271232是的,临时变量将绑定到`const init&amp;`或`int&amp;&amp;`,并且临时变量将在完整表达式**之后**被销毁,即整个`foo(2)(3);`。 (3认同)