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