限定范围的锈蚀寿命实际上是什么意思?
所以,在:
fn v1<'a> (a:~[&'a str]) -> ~[&'a str] {
return a;
}
#[test]
fn test_can_create_struct() {
let x = v1("Hello World".split(' ').collect());
}
我知道,我已阅读 http://static.rust-lang.org/doc/master/guide-lifetimes.html#named-lifetimes ,但我不明白此代码实际上是做什么的.
I know, I've read http://static.rust-lang.org/doc/master/guide-lifetimes.html#named-lifetimes, but I don't understand what this code actually does.
该函数基本上像通用fn一样被参数化,但是具有生命周期,这是我在IRC通道上看到的内容,但是可以想象是这样,并且我们有一个L,这是一些特定的生命周期结构.
The function is basically parametrized like a generic fn but with a lifetime, is what I've seen said on the IRC channel, but lets imagine that is the case, and we have a L, which is some specific lifetime structure.
显然我是在隐式呼叫:
v1::<L>("Hello World".split(' ').collect());
..但我不是.传递给此函数的生命周期是生命周期的 instance ,而不是生命周期的类型,因此注释对我来说没有任何意义.
..but I'm not. The lifetime being passed to this function is an instance of a lifetime, its not a TYPE of lifetime, so that comment doesn't make any sense to me.
我的意思是,我基本上理解了发生的事情(我认为):返回的〜[& str]
具有与调用方作用域相同的生存期,大概是 test_can_create_struct()
函数.这是因为(据我所知),函数 v1
是从调用函数中以生存期 instance 进行调用的.
I mean, I basically understand whats going on (I think): The returned ~[&str]
has the same lifetime as the scope of the caller, presumably the test_can_create_struct()
function. That's because (as I understand it) the function v1
is invoked with the lifetime instance from the calling function.
非常混乱.
然后,我们还有其他一些示例,例如: https://gist.github.com/bvssvni/8970459
Then we have some other examples like: https://gist.github.com/bvssvni/8970459
这是一个片段:
impl<'a> Data<'a> {
pub fn new() -> Data<'a> {
Data { a: None, b: None }
}
pub fn a(&'a mut self, a: int) -> State<'a, Step1> {
self.a = Some(a);
State { data: self }
}
}
现在,我天真地假设 Data<'a>
意味着函数 a()
的生存期实例是相同的.
Now here I naively assumed that the Data<'a>
means that the lifetime instance for the function a()
is the same.
即如果创建一个 Data
( let blah = Data :: new()
)并调用 blah.a()
,则生存期将继承自创建调用;即返回的 State
对象与父 Data
对象一样存在.
i.e. If you create a Data
(let blah = Data::new()
) and call blah.a()
, the lifetime is inherited from the create call; i.e. the State
object returned will exist for as long as the parent Data
object does.
...但是显然这也是错误的.所以我根本不知道生命周期变量到底是什么意思.
...but apparently that's wrong too. So I have just no idea what the lifetime variables mean at all now.
帮助!
最简单的解决方法是退后一步,逐步了解一生到底是什么.
So the easiest way to answer this will be to take a step back and walk you through what a lifetime actually is.
让我们接受一个简单的功能:
Lets take a simple function:
fn simple_function() {
let a = MyFoo::new();
println("{}", a);
}
在此函数中,我们有一个变量 a
.像所有变量一样,此变量会生存一定的时间.在这种情况下,它将保留到功能的末尾.函数结束时, a
死亡.这样, a
的生存期就可以描述为从函数的开头开始,到函数的结尾结束.
In this function, we have a variable, a
. This variable, like all variables, lives for a certain amount of time. In this case, it lives to the end of the function. When the function ends, a
dies. The lifetime of a
, can then be described as starting at the beginning of the function, end ending at the end of the function.
该下一个函数将无法编译:
This next function won't compile:
fn broken_function() -> &MyFoo {
let a = MyFoo::new();
return &a;
}
执行 a
时,您借用 a
的引用.但是,关于借贷的事情是,您应该将借来的东西还给您.Rust对此非常严格,不会让您拥有无法返回的参考.如果您借用的参考资料不再存在,您将无法返回该参考资料,而该信息就不可用了.
When you do &a
, you are borrowing a reference to a
. The thing about borrowing, though, is that you are expected to give the thing you borrowed back. Rust is very strict about this, and won't let you have references you can't return. If the thing you borrowed your reference from isn't around any more, you can't return the reference and that's just not on.
对于我们的 broken_function
意味着什么,因为 a
死于函数的末尾,因此引用无法转义该函数,因为这会使它失效胜过 a
.
What it means for our broken_function
is that, because a
dies at the end of the function, the reference can't escape the function, because that would make it outlast a
.
下一步是这样:
fn call_fn() {
let a = MyFoo:new();
{
let a_ref = &a;
let b = lifetimed(a_ref);
println!("{}", *b);
}
}
fn lifetimed<'a>(foo: &'a MyFoo) -> &'a MyBar {
return foo.as_bar();
}
这里有两个函数,分别是 call_fn
和 lifetimed
,这里有一些微妙的事情,所以我将其分解.
Here are two functions, call_fn
and lifetimed
, there's some subtle stuff going on here, so I'll break it down.
在 call_fn
中,我首先创建一个 MyFoo
的新实例,并将其分配给 a
,然后,我借用一个对的引用a
并将其分配给 a_ref
.借用的事情是,当您进行借用时,生命周期信息将从您要借用的变量转移到引用本身.因此,现在 a_ref
作为变量具有其自身的生存期,该生存期在该内部作用域的开始和结尾处开始和结束,但是 a_ref
的类型也有一个生命周期,即从 a
转移过来的生命.
In call_fn
I first create a new instance of MyFoo
and assign it to a
, then, I borrow a reference to a
and assign it to a_ref
. The thing with borrowing is that when you do a borrow, the lifetime information is transfered from the variable you are borrowing, into the reference itself. So now a_ref
, as a variable, has its own lifetime, which starts and ends at the beginning and end of that inner scope, but the type of a_ref
also has a lifetime, the one transferred over from a
.
具体生命周期无法命名,但是假装我们仍然可以使用数字来实现.如果 a
的生存期为#1
,则 a_ref
的类型为 MyFoo
.当我们将 a_ref
传递给 lifetimed
时,编译器将像其他类型参数一样填充生命周期参数'a
. lifetimed
的返回类型是具有相同生存期的引用,因此编译器会在此处填充空格.有效地唯一调用 lifetimed(foo:&'#1 MyFoo)->&'#1 MyBar
.
Concrete lifetimes can't be named, but lets pretend we can do it anyway by using numbers. If the lifetime of a
is #1
, then the type of a_ref
is &'#1 MyFoo
. When we pass a_ref
to lifetimed
, the compiler fills in the lifetime parameter 'a
like it does for other type parameters. lifetimed
's return type is a reference with the same lifetime, so the compiler fills in the space there. Effectively making a unique call to lifetimed(foo: &'#1 MyFoo) -> &'#1 MyBar
.
这就是生命周期出现在类型参数列表中的原因,它们是类型系统的一部分,如果类型不匹配,那就是错误的.编译器会计算出要编译的函数所需的生存期,因此您不必担心它,但不会在当前函数之外查找以获得更多信息.您需要使用参数来告诉编译器您正在调用的函数,以便它知道一切正常.
This is why lifetimes appear in the type parameter list, they are part of the type system, and if the types don't match up, that's an error. The compiler works out the lifetimes needed in order for the function to compile, so you never have to worry about it, but won't look outside the current function to get more information. You need to use the parameters to tell the compiler about the function you're calling so it knows that everything is ok.
注意事项:您可以明确命名一个生命周期.'static
,这是在程序整个长度上持续存在的事物的寿命.
NB: There is one lifetime you can explicitly name. 'static
which is the lifetime of things that last for the entire length of the program.