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

时间:2014-03-05 03:45:42

标签: rust lifetime

所以,在:

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,但我不明白此代码实际上做了什么

该函数基本上是参数化的,就像通用的fn但有生命周期,是我在IRC频道上看过的,但让我们想象就是这样,我们有一个L,这是一些特定的生命周期结构。

显然我暗中打电话:

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

..但我不是。传递给此函数的生命周期是生命周期的实例,它不是生命周期的类型,因此注释对我没有任何意义。

我的意思是,我基本上了解最新情况(我认为):返回的~[&str]与调用者的范围具有相同的生命周期,可能是test_can_create_struct()函数。那是因为(据我所知),函数v1是使用来自调用函数的生命周期实例调用的。

非常混乱。

然后我们还有其他一些例子: 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()的生命周期实例是相同的。

即。如果您创建Datalet blah = Data::new())并致电blah.a(),则生命周期将从创建调用继承;即,只要父State对象发生,返回的Data对象将存在。

......但显然这也是错的。所以我现在根本不知道生命周期变量的含义。

帮助!

1 个答案:

答案 0 :(得分:19)

所以回答这个问题最简单的方法就是退后一步,引导你了解一生的实际情况。

让我们采取一个简单的功能:

fn simple_function() {
  let a = MyFoo::new();
  println("{}", a);
}

在这个函数中,我们有一个变量a。与所有变量一样,此变量可以存在一段时间。在这种情况下,它一直存在于函数的末尾。当函数结束时,a死亡。然后,a的生命周期可以描述为从函数的开头开始,结束于函数的结尾。

下一个函数将无法编译:

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

执行&a后,您借用 参考a。然而,关于借贷的事情是,你应该把你借来的东西给回来。 Rust对此非常严格,并且不会让您拥有无法返回的引用。如果您借用的参考资料不再存在,那么您无法返回参考资料,而且还没有参考。

对我们的broken_function意味着什么,因为a在函数结束时死亡,引用无法转义函数,因为这会使它超过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_fnlifetimed,这里有一些微妙的内容,所以我会把它分解。

call_fn我首先创建MyFoo的新实例并将其分配给a,然后,我借用a的引用并将其分配给{{1} }}。借用的东西是,当你进行借用时,生命周期信息会从你借来的变量转移到引用本身。所以现在a_ref作为变量有自己的生命周期,它在内部范围的开头和结尾开始和结束,但a_ref 的类型也有一生,一个从a_ref调来的。

具体的生命周期无法命名,但我们假装无论如何都可以使用数字来完成。如果a的有效期为a,则#1类型a_ref。当我们将&'#1 MyFoo传递给a_ref时,编译器会像其他类型参数一样填充生命周期参数lifetimed'a的返回类型是具有相同生命周期的引用,因此编译器会在那里填充空格。有效地拨打lifetimed

这就是为什么生命周期出现在类型参数列表中,它们是类型系统的一部分,如果类型不匹配,那就是错误。编译器计算出函数编译所需的生命周期,因此您不必担心它,但不会在当前函数之外查看以获取更多信息。您需要使用这些参数告诉编译器您正在调用的函数,以便它知道一切正常。


NB :您可以明确指定一个生命周期。 lifetimed(foo: &'#1 MyFoo) -> &'#1 MyBar这是整个程序的整个生命周期。