rust - 生命周期和结构定义的混淆

标签 rust

(我很难掌握 Rust 的生命周期和所有权)

考虑以下 Rust struct定义:

struct MyType<'lifetime> {
    one: &'lifetime u32,
    two: &'lifetime u32
}

我目前对上述定义的解释如下:

I have defined a struct MyType. The <'lifetime> next to its identifier refers to a specific lifetime of any one instance of MyType. The fields one and two are references to u32s, and because they are annotated with 'lifetime, the integers that they refer to are guaranteed to live at least as long as the instance of the struct they belong to.

为了挑战我目前的理解,我创建了这个示例:

fn main() {

    let num1: u32 = 11;

    let instance: MyType;

    { // nested scope
        let num2: u32 = 22;
        instance = MyType {
            one: &num1,
            two: &num2
        };

        println!("{:?}", instance);
    }
}

这段代码编译并运行(打印 MyType { one: 11, two: 22 } ),但它似乎反驳了我的理解:

instancemain 末尾被丢弃1num2在它之前的嵌套范围的末尾被删除,我最初的理解似乎是错误的: two 引用的整数字段“至少与结构实例一样长”。

我哪里错了? 'lifetime 是什么意思?在struct MyType<'lifetime'>实际上指的是?


1:我也不确定这是否正确。

最佳答案

instance gets dropped at the end of main

根据您编写的代码,这是不正确的。您发现了non-lexical lifetimes (NLL)。

在 Rust 中,如果一个值实现了 Drop 特性,那么它只能保证存活到其封闭 block 的末尾。否则,当不再使用时,编译器可以自由地结束其生命周期。由于在 num2 超出范围后您不使用 instance,因此此代码是可以接受的; instance 的生命周期在 println!() 调用中最后一次使用后被缩短,此时 num2 仍然存在。

有几种方法可以使此代码失败。

其中之一是将 println!() 调用移到匿名 block 之外:

fn main() {
    let num1: u32 = 11;

    let instance: MyType;

    { // nested scope
        let num2: u32 = 22;
        instance = MyType {
            one: &num1,
            two: &num2
        };
    }

    // error[E0597]: `num2` does not live long enough
    println!("{:?}", instance);
}

另一种方法是在 MyType 上实现 Drop,这会禁用该类型值的 NLL。

impl Drop for MyType<'_> {
    fn drop(&mut self) { }
}

这将产生:

error[E0597]: `num2` does not live long enough
...
borrow might be used here, when `instance` is dropped and runs the `Drop` code for type `MyType`

关于rust - 生命周期和结构定义的混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72536005/

相关文章:

initialization - 与结构同名的函数

rust - 调用非泛型函数时如何内联提供类型注释?

postgresql - 在 rust-postgres 中使用固定精度数字的正确方法是什么?

reference - 当结构的一个实例需要引用另一个实例时,会出现生命周期问题

enums - 我可以使用枚举作为另一个枚举的值检查器吗?

asynchronous - 从 Tokio 应用程序使用 Actix:混合 actix_web::main 和 tokio::main?

vector - 如何在Vec <T>中将元素从x返回到y?

rust - 为什么递归异步函数需要 Rust 中的“静态参数”?

rust - 我应该在哪里添加明确的生命周期界限?

rust - 如何在不使用 Box 的情况下从特征方法返回匿名类型?