我已经阅读了生命期,并了解每个变量绑定都有生命周期。然而,似乎我无法想到你实际需要使用它们的时间,考虑到编译器在必要时推断它们的确非常棒。
Rust书,我读过。我想要一个简单易懂的例子,即使像我这样的人也是如此!
答案 0 :(得分:3)
当变量(具有一些生命周期)引用另一个不同生命周期的变量时,我们在Rust中使用生命周期参数。
让我们考虑这两个陈述:
let i = 42;
let ref_i = &i;
此处,i
有一定的生命周期,ref_i
有一些其他生命周期。但是,ref_i
的类型会对i
的生命周期进行编码(或者是声音的某种近似值);借用指针的类型写为&'a T
,'a
是指针指示的生命周期。
借用指针只能引用更长生命周期的值,而不是指针的生命周期。如果不是这种情况,则指针最终将悬空,即它将引用不再存在的值。编译器会自动为您验证(只要您不写unsafe
代码);这是C ++等其他系统编程语言所不具备的。但为了验证这一点,编译器必须知道指针引用的值的生命周期;这就是为什么我们在Rust中有生命周期参数的原因。幸运的是,编译器还可以在许多情况下推断生命周期,因此在这些情况下它是透明的。
根据设计,Rust只会进行本地类型推断。编译函数时,编译器不检查其他函数体或其他类型,以验证第一个函数是否正确;它只会查看签名。对于函数,我们有 elision rules ,它们规定何时我们可以省略显式生命周期参数以及编译器将推断它们的内容。对于结构体,我们总是必须明确地提及它们,因为我们几乎总是需要将结构体上的生命周期参数与其他一些项相关联(例如特征impl中特征的生命周期参数,或方法上的返回类型),由于编译器只进行局部类型推断,我们需要在签名中明确地编码这种关联。
这是一个包含借用的结构的简单示例:
struct Wrapper<'a>(&'a str);
impl<'a> Wrapper<'a> {
fn extract(self) -> &'a str {
self.0
}
}
首先,在struct定义中,我们需要为字符串切片引入一个生命周期参数。然后,我们需要参数化impl
,因为Wrapper
需要一个生命周期参数('a
中的impl<'a>
定义生命周期参数'a
1}} Wrapper<'a>
使用生命周期参数)。在extract
上,我们可以参考'a
上定义的impl
生命周期参数,以便函数的返回类型与self.0
的实际类型匹配。