rust “Box”和“&”在生命周期中的行为不同?[副本]

gopyfrb3  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(110)

这个问题已经有答案了

Why do I need to add a lifetime to a function that returns a reference?(1个答案)
21天前关闭。
当我想从函数返回闭包时,我需要使用trait对象。因为这是动态调整大小的,我们当然需要一些间接性。一个很简单的例子是

fn returns_closure() -> Box<dyn Fn(i32) -> i32> {
    Box::new(|x| x + 1)
}

事实上,它的工作原理和预期的一样。然而,当我用一个正常的引用替换Box时,即

fn returns_closure() -> &dyn Fn(i32) -> i32 {
    &(|x| x + 1)
}

我得到错误

--> src/main.rs:70:25
   |
70 | fn returns_closure() -> &dyn Fn(i32) -> i32 {
   |                         ^ expected named lifetime parameter
   |
   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
   |
70 | fn returns_closure() -> &'static dyn Fn(i32) -> i32 {
   |                          +++++++

为什么会这样呢?为什么我在这里需要一个终身注解呢?
一种解释是&只是直接引用闭包(|x| x+1),它在函数结束时立即被删除(没有进一步的注解),而Box类型实际上在堆上创建了这个闭包的副本。
我的理解正确吗?

6yt4nkrj

6yt4nkrj1#

是否需要生存期注解取决于函数签名。在不查看函数实现的情况下,编译器(以及文档的读者)将尝试推断其生存期。rule如下:
如果参数中仅使用了一个生存期(省略与否),则该生存期将分配给所有省略的输出生存期。
在这种情况下,参数中使用的生存期为零(因为没有参数),因此不会推断生存期,您必须显式指定返回值的生存期。在这种情况下,正如编译消息所建议的那样,您将希望使用静态生存期(特别是因为这是一个不捕获任何变量的闭包)。您可以通过在函数签名中写入&'static而不是&来实现这一点。这是一种为调用者提供最大灵活性的引用类型。
为什么会这样呢?为什么我在这里需要一个终身注解呢?
尽管在这种情况下可以推断生存期,但此规则的优点是,在阅读代码时,此函数返回静态生存期的情况更加清楚。就像通常可以推断返回类型是什么一样,显式指定它提供了额外的文档和对代码返回正确类型的完整性检查。
我确实认为Rust的错误消息比必要的更隐晦。返回类型包含借用的值?更准确地说,返回类型是借用值的类型。或者像它通常被称为:推荐信。信息可以直接说:返回类型是具有隐式生存期的引用,但没有参数可从中复制生存期。
而Boxtype实际上在堆上创建了这个闭包的副本。我的理解正确吗?
Box的关键区别在于,Box的内容被复制到堆上,并且每当Box被释放时,Box的内容就会被释放。因此,调用者将获得盒子的所有权,并通过代理获得堆上相关数据的所有权。在静态引用场景中,闭包静态存储在程序中,函数返回对该数据的引用。

相关问题