终身注释,或& str vs String

时间:2014-11-15 21:33:41

标签: rust lifetime

我有一个小库,可以导出带有生命周期注释的结构。现在我尝试从另一个程序中使用它,但似乎我现在也需要在那里使用生命周期注释。基本上我是这样做的:

// in my lib
struct Foo<'a> {
    baz: &'a str
}

// another program
struct Bar {
    foo: Foo
}

其中说Bar必须为Foo定义生命周期:

<anon>:6:10: 6:13 error: wrong number of lifetime parameters: expected 1, found 0 [E0107]
<anon>:6     foo: Foo
                  ^~~

这很容易解决:

struct Bar<'a> {
    foo: Foo<'a>
}

但这意味着我现在还必须为使用Bar的任何事物定义生命周期,依此类推,对吗?如果这是真的,除了使用不需要显式生命周期的类型之外,还有什么方法可以解决这个问题吗?或者最好是使用像String这样的拥有类型?

有点背景,我使用&str,因为我必须调用一个需要作为参数的函数。虽然转换它们没有问题,但它实际上是Vec<(&str, &str)>,所以我的想法是首先使用正确的类型来摆脱转换。我有一种感觉,这是错误的决定,但我知道...:)

1 个答案:

答案 0 :(得分:4)

是的,现在没有办法解决明确的生命周期。考虑它的方法是Foo需要明确关于哪个生命周期与它相关联,因为baz字段依赖于它,因此,例如,编译器知道如果阻止你你试图使Foo的寿命比数据baz所指的要长,或者你可以使用返回“只要baz生活就能生存”的引用的方法。如果您随后将Foo嵌入Bar,则现在Bar需要明确的生命周期,因为Foo取决于它。

如果Foo是“拥有”字符串,意味着Foo应该能够独立于任何可能的生命周期(例如范围)而独立存在,那么它应该是String 1}}。从String转换为切片非常便宜,因为切片仅仅是对现有数据的视图。

但是,如果您总是根据与范围相关联的现有数据构建Foo(例如,传递给包含{{1}的函数的字符串切片}实例等)并且Foo实例不需要超出现有数据的范围,如果您将其设为Foo,则必须将切片转换为{{} 1}}(与反向相比相对较贵)只是将其转换回使用点的切片,在这种情况下,您应将其保留为切片。你当然不应该仅仅为了避免输入明确的生命周期而产生这种性能损失。

你会发现具有显性生命周期的类型非常常见,所以虽然它一开始看起来确实令人担忧,但你会习惯它。