fn foo<'a, T>()
where T : 'a
{
//code a
}
fn foo()
{
//code b
}
在代码a中可以做什么,而在代码b中无法做到呢?
我希望它们是完全相同的,因为我不理解它们之间的区别以及生命周期限定的含义。如果有助于解释用例(例如参数),您可以建议对第一个函数进行补充。
fn foo<'a, T>()
where T : 'a
{
//code a
}
fn foo()
{
//code b
}
在代码a中可以做什么,而在代码b中无法做到呢?
我希望它们是完全相同的,因为我不理解它们之间的区别以及生命周期限定的含义。如果有助于解释用例(例如参数),您可以建议对第一个函数进行补充。
trait Elem {}
struct List<'a> {
v: Vec<Box<dyn Elem + 'a>>,
}
impl<'a> List<'a> {
fn push<T: Elem>(&mut self, t: T) {
self.v.push(Box::new(t));
}
}
error[E0309]: the parameter type `T` may not live long enough
--> src/lib.rs:9:21
|
9 | self.v.push(Box::new(t));
| ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
8 | fn push<T: Elem + 'a>(&mut self, t: T) {
| ++++
List<'a>
只能包含至少与'a
一样长的生命周期的元素。因此,T: 'a
约束适用于这些情况。对于此语法,T: 'static
是最常见的情况,表示该类型可能根本不包含任何局部引用。Cow
可能是一个很好的例子。pub enum Cow<'a, B>
where
B: 'a + ToOwned + ?Sized,
{
Borrowed(&'a B),
Owned(<B as ToOwned>::Owned),
}
lifetime参数允许结构体包含对B的引用,而无需拥有它。由于Cow不是B的所有者,借用检查器需要知道B的生命周期,以防止Cow持有的引用变得悬空。B: 'a
实际上并不是必需的,因为它被 &'a B
隐含了。可以参考这个问答:Does &'a T imply T: 'a?。出于历史原因,它仍然存在。 - undefinedfn foo1<'a, T: 'a>() {...}
和fn foo2<T>() {...}
之间的区别在于,在foo1
中,你能够给'a
命名。在foo2
中,你无法表达与T
相关的显式生命周期界限。由于Rust可能会改变其他约束所暗示的隐式生命周期界限,因此受此约束限制的确切操作可能会随时间而变化。&'a T
时,你隐含地意味着T: 'a
。这以前是不成立的。
Elem
是一个trait,因此底层类型可能是一个引用或者有引用,但也可能不是。 - undefined