昨天在IRC里有一些关于这个问题的讨论,让我隐隐感到不满。
问题是。
你如何定义一个结构的生命周期 来限制它的内容只和 "它本身 "一样长的东西。
即一个 'self
种东西。
我最初的反应是:不能。
如果你创建一个结构 Foo<'a>
的引用来推断与它相关的寿命;除非结构体包含对 本身 (不可能),你不可能有这样的 'self
一生。
有一大堆人在议论,最后我写了 这个游乐场 因此,。
#[derive(Debug)]
struct Bar;
#[derive(Debug)]
struct Foo<'a> {
a:&'a Bar,
b:&'a Bar
}
fn factory<'a>(v1:&'a Bar, v2: &'a Bar) -> Foo<'a> {
return Foo {
a: v1,
b: v2
};
}
fn main() { // <---- Let's call this block lifetime 'one
let a = Bar;
let c = &a; // <-- C has lifetime 'one
{ // <------------ Let's call this block lifetime 'two
let b = Bar;
let mut foo1 = factory(c, c);
foo1.b = &b;
let mut foo2 = factory(&b, &b);
foo2.a = &a;
println!("{:?}", foo1);
println!("{:?}", foo2);
}
}
然而,我现在更困惑了,而不是更少。
所以,从严格意义上讲,在上述。
c
已经 'one
&b
有 'two
'static
> 'one
> 'two
(即: 'two
边界为 'one
). foo1
有 'one
foo2
有 'two
现在,我的困惑。
Foo<'a>
表示 'a
是 最小寿命界限 的实例所能包含的 Foo
.
由于 'one
> 'two
, foo2
应能包含一个 &'one a
;这就可以了。
由于 'two
> 'one
, foo1
应 不 容得下 &'two b
;然而,这样做是可行的。
为什么呢?
看来我的困惑是由两种误解之一造成的;要么。
要么是... foo1
其实 Foo<'two>
,不 Foo<'one>
.
我不明白为什么会是这样,因为它是在 factory<'a>
哪儿 <'a>
是一生的 c
;这就是 'one
,不 'two
. 绝对没有办法 c
可以 &'two
在上面的例子中。寿命 'two
在功能工厂中是不可用的,其中 Foo
是创建的。
2)结构寿命并不是我所理解的工作方式,即一生中的 'a
关于 Foo
实例创建后,可以以某种方式改变(例如,在移动时?
...但我不知道是哪一种。
引用上的寿命参数是 共变:它们可以用以下词语代替:"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"、"我"。较短 必要的时候,一辈子。
基本上,你把它弄错了。当你有一个 &'one Bar
的值,不能用 较短 辈子 'two
这里),否则当执行离开 'two
范围。然而,当你有一个 &'two Bar
您可以将一个引用分配给一个寿命较长的值(如 'one
和 'static
),因为在引用之前,引用就会超出范围。
为什么你的程序会被编译? 编译器并不仅仅使用来自调用 factory
以选择适当的寿命。它还使用来自分配的信息. &a
有类型 &'one Bar
和 &b
有型 &'two Bar
. 因为 'two
开始于 'one
并在 'one
,编译器可以 逼迫 a &'one Bar
到 &'two Bar
. 用面向对象的术语来说,一个 &'one Bar
是一个 &'two Bar
(&'one Bar
是 &'two Bar
). 就像在Java中,你可以通过一个叫 String
作为一个函数的参数,该函数期待一个 Object
. 在Java中,类的子类型关系是子类是其父类的子类型,但寿命的子类型关系是较长的寿命是较短的寿命的子类型。
这意味着,我们已经找到了一个共同的类型,即为 &a
和 &b
: &'two Bar
. 因此,编译器推断出 'two
对于 'a
在呼叫中 factory
.
请注意 foo2
在赋值时不会改变,一个值的类型总是静态的。