简体   繁体   English

什么生锈的生命周期实际上意味着什么?

[英]What does a scoped lifetime in rust actually mean?

So, in: 所以,在:

fn v1<'a> (a:~[&'a str]) -> ~[&'a str] {
  return a;
}

#[test]
fn test_can_create_struct() {
  let x = v1("Hello World".split(' ').collect());
}

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 . 我知道,我已经阅读了http://static.rust-lang.org/doc/master/guide-lifetimes.html#named-lifetimes ,但我不明白这段代码实际上做了什么。

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. 该函数基本上是参数化的,如通用fn,但有一生,是我在IRC频道上看到的,但让我们想象就是这样,我们有一个L,这是一些特定的生命周期结构。

Apparently I'm implicitly calling: 显然我隐含地称:

v1::<L>("Hello World".split(' ').collect());

..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. 传递给这个函数的生命周期是一个生命周期的实例 ,它不是生命周期的类型,因此注释对我没有任何意义。

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. 我的意思是,我基本上理解发生了什么(我认为):返回的~[&str]具有与调用者范围相同的生命周期,可能是test_can_create_struct()函数。 That's because (as I understand it) the function v1 is invoked with the lifetime instance from the calling function. 那是因为(据我所知),函数v1是用来自调用函数的生命周期实例调用的。

Very confusing. 很混乱。

Then we have some other examples like: https://gist.github.com/bvssvni/8970459 然后我们有一些其他的例子: https//gist.github.com/bvssvni/8970459

Here's a fragment: 这是一个片段:

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 }
  }
}

Now here I naively assumed that the Data<'a> means that the lifetime instance for the function a() is the same. 现在我天真地假设Data<'a>意味着函数a()的生命周期实例是相同的。

ie If you create a Data ( let blah = Data::new() ) and call blah.a() , the lifetime is inherited from the create call; 即如果您创建一个Datalet blah = Data::new() )并调用blah.a() ,则生命周期将从create调用继承; ie the State object returned will exist for as long as the parent Data object does. 即,只要父Data对象执行,返回的State对象将存在。

...but apparently that's wrong too. ......但显然这也是错的。 So I have just no idea what the lifetime variables mean at all now. 所以我现在根本不知道生命变量的含义。

Help! 救命!

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);
}

In this function, we have a variable, a . 在这个函数中,我们有一个变量, 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. 当函数结束时, a死了。 The lifetime of a , can then be described as starting at the beginning of the function, end ending at the end of the function. 然后, a的生命周期可以描述为从函数的开头开始,结束在函数的结尾。

This next function won't compile: 下一个函数将无法编译:

fn broken_function() -> &MyFoo {
  let a = MyFoo::new();
  return &a;
}

When you do &a , you are borrowing a reference to a . 当你做&a ,你的贷款总额参考 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. Rust对此非常严格,并且不会让您拥有无法返回的引用。 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. 如果您借用的参考资料不再存在,那么您无法返回参考资料,而这只是没有参考。

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 . 这意味着什么我们broken_function是,因为a死在函数结束时,参考无法逃避的功能,因为这将使其成为拖垮a

The next step is this: 下一步是这样的:

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();
}

Here are two functions, call_fn and lifetimed , there's some subtle stuff going on here, so I'll break it down. 这里有两个函数, call_fnlifetimed ,这里有一些微妙的东西,所以我会把它分解。

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 . call_fn我首先创建一个新的实例MyFoo并将其分配给a的话,我借到参考a并将其分配给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_ref有它自己的生命周期,它在该内部范围的开始和结束处开始和结束,但是a_ref的类型有一个生命周期,一个从a转移的生命周期。

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 . 如果寿命a#1 ,则类型 a_ref&'#1 MyFoo When we pass a_ref to lifetimed , the compiler fills in the lifetime parameter 'a like it does for other type parameters. 当我们将a_ref传递给lifetimed ,编译器会填充a_ref参数'a就像它对其他类型参数一样。 lifetimed 's return type is a reference with the same lifetime, so the compiler fills in the space there. lifetimed的返回类型是具有相同生命周期的引用,因此编译器填充了那里的空间。 Effectively making a unique call to lifetimed(foo: &'#1 MyFoo) -> &'#1 MyBar . 有效地对lifetimed(foo: &'#1 MyFoo) -> &'#1 MyBar进行独特的调用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. 您需要使用参数告诉编译器您正在调用的函数,以便它知道一切正常。


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. 'static ,这是持续整个程序的事物的生命周期。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM