如何初始化具有生命周期的变量?

Posted

技术标签:

【中文标题】如何初始化具有生命周期的变量?【英文标题】:How to initialize a variable with a lifetime? 【发布时间】:2015-03-22 10:05:22 【问题描述】:

我有以下代码,但不知道如何让它工作:

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

【问题讨论】:

我不知道你想做什么,但你正在做的是试图创建一个对生命周期小于 'a.它具有函数体的生命周期。 我正在尝试使用生命周期参数将该变量暴露给身体外部。如果可能的话。 该变量在函数体之外已失效。如果您可以访问它,您将覆盖其他内存。错误消息(请参阅is.gd/ju7hFZ)准确地告诉您。 由于static 升级,这些函数现在进行编译(请参阅Why can I return a reference to a local literal but not a variable? 【参考方案1】:

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

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

本地分配给函数本身并在您从函数(堆栈)返回时销毁 动态地在所有函数(堆)共用的内存区域中

引用 (&amp;) 是指向内存区域的指针。它可以指向本地堆栈或堆。由于动态分配在性能方面比在堆栈上写入要昂贵得多,因此 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

你可以返回值

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

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

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

你可以阅读更多关于'staticin the Rust Reference的信息。

从 Rust 1.21 开始,这个“静态提升”现在会自动为您执行,并且您的原始代码可以编译。它创建了 static FIVE 的等价物。

【讨论】:

放弃我自己正在进行的答案,但我想指出第三种选择:如果它总是返回5,或任何有限的答案集,你可以返回对静态变量的借用引用:static FIVE: isize = 5;,然后作为函数的结果返回 &amp;FIVE【参考方案2】:

另一种理解原因的方法

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

不能工作如下。 'a 是函数的生命周期参数;也就是说,选择这个参数的实际值的是调用者,而不是函数本身。比如调用者可以选择'staticlifetime:

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

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

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

【讨论】:

【参考方案3】:

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

它们不是让某些东西按要求生存下去的指令,而是一种一致性检查,可确保代码确实按照它所说的那样工作。

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

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

【讨论】:

以上是关于如何初始化具有生命周期的变量?的主要内容,如果未能解决你的问题,请参考以下文章

java 静态变量生命周期(类生命周期)

java 静态变量生命周期(类生命周期)(转)

Bean的生命周期流程-上

Bean的生命周期流程-上

#yyds干货盘点#愚公系列2022年10月 微信小程序-应用生命周期和全局变量

c++类中 各种成员的生命周期?