昨天在IRC中对此进行了一些讨论,这让我感到有些模糊不满.
问题是:
如何在结构上定义生命周期以将其内容限制为仅与"本身"一样长的内容.
即一种'自我的东西.
我最初的反应是:你做不到.
如果你创建一个struct Foo <'a>,那么与它相关的生命周期是从它包含的引用中推断出来的; 除非结构包含对自身的引用(不可能),否则你不能拥有这种"自我生命".
有一堆关于它的喋喋不休,最后我写了这个围栏结果:
#[deriving(Show)]
struct Bar;
#[deriving(Show)]
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);
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我现在更困惑而不是更少.
因此,严格意义上的:
现在,我的困惑:
Foo <'a>表示'a是Foo实例可以包含的最小生命周期限制.
由于'one>'两个,foo2应该能够包含一个&'one a; 这很有效.
由于'two>'一,foo1 不应该包含''两个b; 然而'这是有效的.
为什么?
看来我的混淆是由于两种错误观念之一造成的; 之一:
1)foo1的实例是面对Foo <'two>,而不是Foo <'one>.
我不明白为什么会这样,因为它是在工厂生产的,其中<'a>是c的寿命; 这是'一个,不是'两个.在上面的例子中,c绝对没有办法.在创建Foo的函数工厂中,生命周期'2'不可用.
2)结构生命周期不起作用,我理解它们的工作方式; 即.一个Foo实例上的'a'生命周期可以在创建实例之后以某种方式改变(例如,在移动中?)
......但我不知道哪一个.
参考文献的寿命参数是逆变的:必要时可以用更短的寿命代替它们.
基本上,你有错误的方法.如果有a &'one Bar,则无法为具有较短生命周期的值(例如'two此处)分配引用,否则在执行离开'two作用域时引用将悬空.但是,如果有a &'two Bar,则可以为具有更长生命周期的值(例如'oneand 'static)分配引用,因为引用将在引用之前超出范围.
你的程序为什么要编译?编译器不仅使用来自调用的信息factory来选择适当的生命周期; 它还使用来自作业的信息.&a有类型&'one Bar和&b类型&'two Bar.因为'two在'one之前和之后开始'one,编译器可以强制 a &'one Bar到a &'two Bar.在面向对象的术语中,a &'one Bar 是a &'two Bar(&'one Bar是其子类型&'two Bar).就像在Java中一样,你可以将一个String参数作为一个参数传递给一个期望的函数Object.只是因为子类型关系是生命周期的另一种方式.
这意味着我们找到了一个常见的类型:&a和.因此,编译器推断为在呼叫.&b&'two Bar'two'afactory
请注意,foo2分配时的类型不会改变; 值的类型始终是静态的.
| 归档时间: |
|
| 查看次数: |
372 次 |
| 最近记录: |