函数调用是否有生命,或只有变量?

时间:2014-03-12 17:10:21

标签: rust

编辑:这个问题显然太复杂了。这是一个更简单的例子,它解释了我想要问的内容:

#[feature(macro_rules)];    
macro_rules! trace(
  ($($arg:tt)*) => (
    { let x = ::std::io::stdout().write_line(format_args!(::std::fmt::format, $($arg)*)); println!("{}", x); }
  );
)

#[deriving(Show)]
struct Foo<T> {
  data: ~T
}

impl<T> Foo<T> {

  // Notice how the 'pontless_marker' variable is passed into this function for
  // no reason other than that it allows us to copy the lifetime scope of the
  // 'marker' variable in the test below, so the lifetime of the returned pointer
  // is valid for that block.
  fn returns_to_scope_with_marker<'a>(&'a self, pointless_marker:&'a int) -> &'a ~T {
    return &self.data;
  }

  // This doesn't work, but it should. You should be able to invoke this function
  // as something like: let marked = bar.returns_to_scope::<LIFETIME???>();
  /*
  fn returns_to_scope<'a>(& self) -> &'a ~T {
    return &self.data;
  }
  */
}

#[test]
fn test_lifetime_return_scope() {
  let bar = Foo { data: ~Foo { data: ~10 } };
  {
    let marker = 10;
    let marked = bar.returns_to_scope_with_marker(&marker);
    trace!("{:?}", marked);
  }
}

参见&#39; pointless_marker&#39;在上面的例子中。

这是我想要避免的。如果该函数也被输入为blah&lt;&#39; a&gt;,我觉得我应该能够使用x.blah ::&lt;这里有东西&gt;()来显式调用它。

那是不是不可能?

1 个答案:

答案 0 :(得分:1)

好的,这里有希望解决问题的代码:

#[feature(macro_rules)];    
//Macro rules is unchanged

#[deriving(Show)]
struct Foo<'a, T> {
  data: &'a T
}

impl<'a, T> Foo<'a, T> {

  fn returns_to_scope(&'a self) -> &'a T {
    self.data
  }
}

fn main() {
  let bar = Foo { data: &Foo { data: &10 } };
  {
    let marked = bar.returns_to_scope();
    trace!("{:?}", marked);
  }
}

我将逐行(但不按顺序)并解释问题是什么以及如何解决。

首先,你说你想避免警告并避免发送无意义的变量。我同意这些参数是不必要的。为避免向函数添加变量及其参数,生命周期参数将添加到implstruct定义中,如下所示:

 struct Foo<'a, T> 
 ...
 impl<'a, T> Foo<'a, T> 
 // note: impl<'a,T> is mandatory, because we can say <'a, int> for example
 //       which is not what we want 

'a是一个生命周期参数,它充当另一种泛型类型(即T)。

*如果我们有'a的生命周期,我们需要将其与某些内容联系起来......我们将在文本稍后修复fn returns_to_scope后返回此部分,但很明显数据将获得生命周期 - 它是struct Foo中唯一的值,并且它返回的函数需要类似&'a T的东西。

现在,我们可以在fn returns_to_scope函数上看起来更好一些。如果你看看原来的功能,你几乎就是正确的。

 fn returns_to_scope<'a>(& self) -> &'a ~T {
   return &self.data;
 }

让我错误的第一件事就是你有一个&~指针(&'a ~T)。为什么?您是否理解它是指向堆上分配的指针的堆栈指针?除非你做一些指向杂技的指针,否则它并没有用,但我认为这是一个错误。如果不是很好,你总是可以制作一个~T value并借用它。

所以你希望你的returns_to_scope以某种方式返回self.data字段,如果你要返回一个属于struct Foo的字段,我认为使用相同的生命周期作为结构是更明智的Foo,该领域属于;所以我将描述改为:

fn returns_to_scope(&self) -> &'a T

我省略了<'a>泛型参数,因为我不需要在'a生命周期内概括此函数,'a生命周期是我们通过借用免费获得它的结构的一部分结构。但是我忘了说&self上的生命周期,所以编译器会抱怨,我只是将&self更改为使用'a生命周期进行注释。

fn returns_to_scope(&'a self) -> &'a T

为了画龙点睛,因为Rust只需省略;即可返回字段,我可以写:

fn returns_to_scope(&'a self) -> &'a T {
   self.data
}

而不是return self.data;

现在我们看到结构中的字段是'a生命周期的自然候选者,所以

data: &'a T

被添加到struct Foo中,所有部分现已就绪。