如何使用生命周期初始化变量?

时间:2015-01-23 11:15:36

标签: rust lifetime

我有以下代码,不知道如何使其正常工作:

fn new_int<'a>() -> &'a isize {
    &5
}

fn main() {
    let x = new_int();
}

或另一次尝试:

fn new_int<'a>() -> &'a isize {
    let a: &'a isize = &5;
    a
}

fn main() {
    let x = new_int();
}

3 个答案:

答案 0 :(得分:10)

你不能。生命周期参数不允许您选择值存在多长时间,它只允许您与编译器通信两个或多个引用相关的&#34;相同的记忆,并期望共享相同的生命。

一个函数(例如你的new_int)可以用两种方式分配内存:

  • 本地存在于分配给函数本身的区域(堆栈)中,并在从函数返回时被销毁
  • 动态地存储在所有函数共有的内存区域中(通常称为&#34;堆&#34;,虽然这在所有情况下都不一定正确)

引用(&)是指向内存区域的指针。它可以指向本地堆栈,也可以指向&#34;堆&#34;。由于动态分配在性能方面比在堆栈上写入要昂贵得多,因此Rust默认使用堆栈(您必须使用Box来执行动态分配)。

因此,简而言之,这就是您的代码非法的原因:

fn new_int<'a>() -> &'a isize {
    let a: &'a isize = &5; // write 5 on the local stack
    a // return a pointer to that area of memory
} // the area of memory where I wrote 5 is destroyed here,
  // so the pointer I'm trying to return is not valid

您可以返回值

fn new_int() -> isize {
    5
}

fn main() {
    let a = new_int(); // the value 5 (not a pointer) is copied into a
}

或执行动态分配(在isize的情况下是过度的,但如果你真的使用大型结构则可能有意义)

fn new_int() -> Box<isize> {
    Box::new(5)
}

fn main() {
    let a = *new_int();
}

或者,您可以在函数外部分配内存并在函数中对其进行变更。您通常不会为原始类型执行此操作,但在某些情况下(例如数据流)有意义:

// new_int does not return anything. Instead it mutates
// the old_int in place
fn new_int(old_int: &mut isize) {
    *old_int = 5;
}

fn main() {
    let mut a = 2; // memory for an int is allocated locally
                   // in main()
    new_int(&mut a); // a mutable reference to that memory is passed
                     // to new_int, that overwrites it with another value
}

作为@dk mentions in the comment below,,在这种特定情况下(即你的函数总是返回5或其他一些静态已知的值,而不是函数动态计算的东西)你也可以返回一个'static生命周期的引用:

fn new_int<'a>() -> &'a isize {
    static FIVE: isize = 5;
    &FIVE
}

您可以详细了解&#39; static in the Rust Reference

从Rust 1.21开始,这个&#34;静态促销&#34;现在自动执行,原始代码编译。它创建了等效的static FIVE

答案 1 :(得分:5)

了解原因的另一种方法

fn new_int<'a>() -> &'a isize {
    &5
}

无法正常工作如下。 'a是函数的生命周期参数;也就是说,调用者选择此参数的实际值,而不是函数本身。例如,调用者可以选择'static生命周期:

let i: &'static isize = new_int();

但是,&5的生命周期不能为'static,因此该功能会被拒绝。

换句话说,这种声明基本上是说“我可以给你一个你想要的任何生命的参考”。当然,只有从函数返回的引用的生命周期为'static时,这才有效,这是可能的最长生命周期。这就是DK。顺便说一下。

答案 2 :(得分:0)

生命周期仅描述代码已经在做什么。它们不会以任何方式影响代码的行为。

它们并不是使某些东西活到需要的时间的指令,而是一种一致性检查,以确保代码实际执行所声明的操作。

实际上,Rust在检查了代码后会删除所有生存期,然后在不了解生存期的情况下编译代码。

变量在范围结束时被销毁,这就是它们的生命周期。您不能说他们没有这样做。