繁体   English   中英

为什么这个递归lambda函数不安全?

[英]Why is this recursive lambda function unsafe?

这个问题来自Can lambda函数是递归的吗? 接受的答案说下面显示的递归lambda函数有效。

std::function<int (int)> factorial = [&] (int i) 
{ 
    return (i == 1) ? 1 : i * factorial(i - 1); 
};

但是, 评论指出了这一点

这样的功能无法安全返回

,原因在此评论中提供

返回它会破坏局部变量,并且该函数具有对该局部变量的引用

我不明白原因。 据我所知,捕获变量等同于将它们保留为数据成员(根据捕获列表按值或按引用)。 那么在这种背景下什么是“局部变量”呢? 此外,即使在g++ 7.4.0上使用-Wall -Wextra -std=c++11选项,下面的代码也能正确编译和工作。

#include <iostream>
#include <functional>

int main() {

    std::function<int (int)> factorial = [&factorial] (int i)
    {
        return (i == 1) ? 1 : i * factorial(i - 1);
    };

    std::cout << factorial(5) << "\n";

}

为什么功能不安全? 这个问题仅限于此函数,还是整个lambda表达式?

这是因为为了递归,它使用类型擦除并通过引用捕获类型擦除容器。

这具有允许在内部使用lambda的效果,通过使用std::function间接引用它。

但是,要使其工作,它必须通过引用捕获std::function ,并且该对象具有自动存储持续时间。

您的lambda包含对本地std::function的引用。 即使你通过副本返回std::function ,lambda仍将引用旧的,死亡。

要使安全性返回递归lambda,您可以在auto参数中将lambda发送给自身并将其包装在另一个lambda中:

auto factorial = [](auto self, int i) -> int { 
    return (i == 1) ? 1 : i * self(self, i - 1); 
};

return [factorial](int i) { return factorial(factorial, i); };

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM