我正试图将我的头脑包裹在Rust的生命周期中(因为官方指南并没有真正解释它们)。
生锈时间是仅参考参考,还是它们也可以参考基本/原始值?
答案 0 :(得分:5)
生命周期是值与对所述值的引用之间的联系。
为了理解这个链接,我将使用一个破碎的并行:房屋和地址。
house 是一个物理实体。它建在一块土地上,有时会生活几十年或一百年,在此期间可能会多次翻修,很可能会在某些时候被毁坏。
地址是一个逻辑实体,它可能指向房屋,或指向其他物理实体(字段,学校,火车站,公司的总部......)。 / p>
房屋的生命周期相对清晰:它代表房屋可用的持续时间,从房屋建造的那一刻到房屋被毁坏的那一刻。在这段时间里,这所房子可能经过多次翻修,过去简单的小屋可能最终成为一个完整的庄园,但这对我们来说并不重要;为了我们的目的,这些房子是生活贯穿这些转变。只有它的创造和最终破坏才有意义......即使在我们撕下屋顶时没有人碰巧在卧室里也可能会更好。
现在,想象一下你是一名房地产经纪人。你不保留你在办公室出售的房屋,这是不切实际的;但是,请保留他们的地址!
没有终身的概念,你的客户会不时抱怨,因为你发送给他们的地址......是垃圾场的地址,而不是那个可爱的两层房子你有摄影的地方。您可能还会从警察局得到一些询问,询问为什么人们在刚刚被摧毁的房子里找到了从您办公室拿到小册子的人,随后的诉讼可能会关闭您的业务。
这显然对您的业务构成风险,因此您应该寻求更好的解决方案。如果每个地址都可以标记它所指的房子的生命周期,那么你知道不要让人们去死(或失望)吗?
您可能已经认识到垃圾转储中的C手动内存管理策略;在C中,由房地产经纪人开发人员决定,确保您的地址(指针/参考)总是指居住的房屋。
然而,在Rust中,引用标记有一个特殊标记:'enough
;它表示所引用值的生命周期的下限。
当编译器检查您对引用的使用是否安全时,它会询问以下问题:
值还活着吗?
这个价值是否会在100年后存在并不重要,只要它长期'enough
用于你的使用。
答案 1 :(得分:2)
不,他们也提到了价值观。如果从背景中不清楚他们将活多久,他们也必须注释。然后它被称为终身绑定。
在下面的示例中,有必要指定引用的值至少与引用本身一样长:
use std::num::Primitive;
struct Foo<'a, T: Primitive + 'a> {
a: &'a T
}
尝试删除+ 'a
,编译器会抱怨。这是必需的,因为T
可以是实现Primitive
的任何内容。
答案 2 :(得分:1)
是的,它们只引用引用,但这些引用可以引用基本类型。 Rust不像Java(和类似的语言)那样区分原始类型(通过值传递)和更复杂的类型(Java中的对象),它们通过引用传递。复杂类型可以在堆栈上分配并按值传递,并且可以将引用转换为基本类型。
例如,这是一个函数,它接受i32
的两个引用,并返回对较大引用的引用:
fn bigger<'a>(a: &'a i32, b: &'a i32) -> &'a i32 {
if a > b { a } else { b }
}
它使用生命周期'a
来表示返回引用的生命周期与传入的引用的生命周期相同。
答案 3 :(得分:0)
当您在代码中看到生命周期注释(例如'a
)时,几乎总是涉及引用或借用指针。
借用指针的完整语法是&'a T
。 'a
是引用的生命周期。 T
是指示物的类型。
结构和枚举可以有生命周期参数。这通常是包含借用指针的struct或enum的结果。将借用指针存储在结构或枚举中时,必须明确说明指示对象的生命周期。例如,标准库中的Cow
枚举包含其中一个变体中的借用指针。因此,它有一个生命参数,用于借用指针的类型来定义指示对象的生命周期。
Traits可以具有类型边界,也可以具有生命周期限制。生命期界限表示该特征的具体实现中所有借用指针有效的最大区域(即它们的指示对象是活着的)。如果实现不包含借用
指针,然后生命周期被推断为'static
。生命周期边界可以出现在类型参数定义中,where
子句和特征对象中。
有时,您可能希望使用lifetime参数定义结构或枚举,但没有相应的值来借用。您可以使用标记类型(例如ContravariantLifetime<'a>
)来确保生命周期参数具有正确的方差(ContravariantLifetime
对应于借用指针的方差;没有标记,生命周期将是双变量,这意味着一生可以用任何其他生命代替......不是很有用!)。 See an example of this use case here.