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

How to initialize a variable with a 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();
}

你不能。生命周期参数不允许您选择一个值的生命周期,它只允许您向编译器传达两个或多个引用与同一内存“相关”并且预期共享相同的生命周期。

一个函数(就像你的例子中的new_int)可以通过两种方式分配内存:

  • 本地在分配给函数本身的区域中,当您从函数(堆栈)return中销毁
  • 在所有函数(堆)共有的内存区域中动态地

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

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

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

您可以return值

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) // a Box allocates memory and writes in the heap
}

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
}

作为 ,在这种特定情况下(即您的函数始终 returns 5 或其他一些静态已知值,而不是由函数动态计算的值)您还可以 return 具有 'static 生命周期的引用:

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

您可以阅读更多关于'static in the Rust Reference.

从 Rust 1.21 开始,这种“静态提升”现在会自动为您执行,并且您的原始代码会编译。它创建相当于 static FIVE.

理解原因的另一种方式

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

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

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

但是,&5 不能有 'static 生命周期,因此函数被拒绝。

换句话说,这样的声明本质上是"I can give you a reference of any lifetime you want"。当然,这仅在函数返回的引用的生命周期为 'static 时才有效,这是可能的最大生命周期。 DK就是这样。顺便说一下。

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

它们不是让某物按要求活多久的指令,而是一种一致性检查,可确保代码确实按照它所说的去做。

事实上,Rust 在检查代码后将所有生命周期从代码中剥离,然后在不知道生命周期的情况下编译代码。

变量在其作用域结束时被销毁,这就是它们的生命周期。你不能说声明他们没有这样做。