我有以下 struct
:
struct PeekableRead<'a, R: Read> {
reader: &'a mut R,
peeked_octet: Option<u8>,
}
哪个 rustc
不喜欢:
…:27:1: 30:2 error: the parameter type `R` may not live long enough [E0309]
…:27 struct PeekableRead<'a, R: Read> {
…:28 reader: &'a mut R,
…:29 peeked_octet: Option<u8>,
…:30 }
…:27:1: 30:2 help: run `rustc --explain E0309` to see a detailed explanation
…:27:1: 30:2 help: consider adding an explicit lifetime bound `R: 'a`...
…:27:1: 30:2 note: ...so that the reference type `&'a mut R` does not outlive the data it points at
…:27 struct PeekableRead<'a, R: Read> {
…:28 reader: &'a mut R,
…:29 peeked_octet: Option<u8>,
…:30 }
如果我将生命周期添加到 R
,如 R: Read + 'a
,则可以 . 但为什么?引用上的 'a
不指定生命周期吗?一定要 reader: &'a mut R
,只要结构本身就可以 struct PeekableRead<'a>
,因此,"long enough"?
奇怪的是,我似乎需要两者兼顾;如果我将 'a
添加到 R
并将其从引用中删除,我仍然会得到 error: missing lifetime specifier
. 我获得成功编译的唯一方法是使用两者,但对我来说,它们似乎冗余地指定了相同的东西 .
(另外,为什么 rustc
在输出中两次输出 struct
?第二个看起来像是在做什么的建议,但看起来和我拥有的完全相同......)
2 回答
它指定引用的生存期,但不指定指向的值的生命周期 . 这解释了你的观察结果
为了使结构有效,我们需要两者:指向的值必须仍然存活,引用也必须如此 . (虽然逻辑上,第二个条件暗示了第一个条件,因为引用永远不会超过它指向的值 . ) .
参考上的寿命参数指定了所指对象的寿命(即参考指向的对象) . 该对象可以是引用,也可以是包含一个或多个引用的复杂对象 . 但是,当你使用特征时,这些引用背后的对象的生命周期有些隐藏(特征本身不知道那些生命周期);生命周期边界是让编译器正确推理这些生命周期的原因 .
在引用后面使用泛型类型时,需要添加一个绑定以确保该类型的实例不包含比对这些实例的引用短的引用 . 仅基于您使用类型的方式不会隐式添加边界:边界不应基于结构中哪些字段的详细信息以及您定义它们的类型而更改 .
例如,类型
&'f File
(对于每个'f
)实现Read
. 我们可以用这种类型实例化PeekableRead
:这给了我们一个PeekableRead<&'f File>
.PeekableRead<&'f File>
存储对&'f File
的可变引用,因此reader
字段的具体类型为&'a mut &'f File
. 为了使这样的引用有效,'a
必须短于或等于'f
. 如果'f
短于'a
,则可以将&'f File
替换为在删除引用之前将丢弃的&'f File
,从而导致悬空指针 . 当您将'a
绑定到R
时(即,当您编写R: Read + 'a
时),您说“R
的实例必须超过'a
”(即R
可能不包含短于'a
的引用) .