Rust中Vec<&T>的生命周期:复杂的语法

3

我正在学习官方的Rust编程书籍。在我的程序中遇到了一个奇怪的语法:

pub struct Shelf<'a> {
    items: Vec<&'a Item<'a>>, // => working as expected
    //items: Vec<Item<'a>>, // => not working
    //items: Vec<&'a Item>, // => not working
}

Item是一个包含指向其他类型的引用的结构体:

pub struct Item<'a> {
    owner: &'a Owner,
    name: String,
    avg_rating: u32,
    status: ItemStatus,
}

pub struct Owner {
    pub name: String,
}

我觉得语法`items: Vec<&'a Item<'a>>`很奇怪,而且我不认为我做对了...我的意思是我想要一个包含对`Item`的引用的`Vec`,并且只要其中包含的对`Item`的引用本身有效,那么这个`Vec`就是有效的。难道不应该是`items: Vec<&'a Item>`吗?

1
items: Vec<&'a Item> 中,您没有在 Item 中指定生命周期参数 'a。编译器在这里不会做任何假设,因此仍然需要指定它。相关问题:https://dev59.com/_FwZ5IYBdhLWcg3wTOzr 和 https://stackoverflow.com/q/43712228/1233251 - E net4
1个回答

9

您需要指定两种生命周期:

  • 您的向量包含对项目的引用。
  • 每个项目都包含对其所有者的引用。

您需要指定每种类型的引用存活时间。如果您编写Vec<&'a Item<'b>>,第一个生命周期('a)指定项目引用的存活时间,第二个生命周期('b)指定所有者引用的存活时间。

当您编写Vec<Item<'a>>时,编译器不知道项目的生命周期有多长。

当您编写Vec<&'a Item>时,编译器不知道所有者的生命周期有多长。

当您在两个位置使用相同的生命周期(Vec<&'a Item<'a>>)时,您告诉编译器两个生命周期相同,这意味着项目必须与其所有者完全一样长。这可能过于严格,根据您的用例,最好告诉编译器项目的生命周期不能超过其所有者的生命周期:

pub struct Shelf<'a, 'b: 'a> {
    items: Vec<&'b Item<'a>>,
}

谢谢,这对我很有帮助!它还强调了在“容器”结构中持有引用是一个不好的想法,我应该组织我的代码直接拥有结构体中的东西,而不是引用。因此,在我的例子中,我应该颠倒逻辑,让“Item”包含对“Owner”的引用,而是应该像这样制作我的结构体“Owner”:pub struct Owner { pub name: String, pub items: Vec<Item>, }并避免所有生命周期的复杂性。 - Gilles
我能问一下为什么包含Vec<Something>的结构体需要一个lifetime吗?Vec拥有所有Something类型的对象(它们不是引用),而结构体拥有Vec,因此在生命周期方面应该没有问题。但是它仍然需要一个显式的Something lifetime。 - Andrei Nikolaenko
@AndreiNikolaenko,您需要用实际的代码提出一个新问题。这个问题涉及到引用向量,如果您没有引用,就不需要指定生命周期。如果编译器仍然需要生命周期,则是另一个问题。 - Jmb
@Jmb 谢谢,看起来你已经回答了我的问题。我的 Vec<Something> 不存储对 Something 的引用,但 Something 中有引用,在我移除它们时,生命周期就不再需要了。 - Andrei Nikolaenko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接