You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于Rust中E0716报错及三种相似代码编译差异的疑问

Rust生命周期:三段相似代码编译结果不同的原因解析

第一段代码:编译报错的原因

#[derive(Debug)]
struct Test {
    val: i32
}

fn main() {
    let a:&Test;
    let b = 32;

    a = &Test {
        val: b
    };

    println!("{:?}", a.val);
}

编译错误error[E0716]: temporary value dropped while borrowed的核心原因是临时值生命周期无法匹配提前声明的引用变量:

  • 提前声明的a是一个生命周期覆盖整个main函数的引用变量;
  • 赋值语句中创建的Test { val: b }是临时值,它的构造依赖于当前作用域的变量b,Rust编译器不会对这类临时值进行生命周期提升,它会在当前语句执行完毕后立即被销毁;
  • 这就导致a持有了一个已经被销毁的临时值的引用,形成悬垂引用,触发编译错误。

第二段代码:编译通过的原因

#[derive(Debug)]
struct Test {
    val: i32
}

fn main() {
    let a:&Test;
    let b = 32;

    a = &Test {
        val: 5
    };

    println!("{:?}", a.val);
}

仅将val改为常量5后编译通过,是因为触发了Rust的临时值生命周期提升规则:

  • 当临时值由常量表达式构造(不依赖任何当前作用域的变量)时,编译器会自动将这个临时值的生命周期延长到包含该引用的作用域(也就是整个main函数周期);
  • 此时a的引用生命周期和临时值的生命周期完全匹配,不会出现悬垂引用,因此可以正常编译。

第三段代码:编译通过的原因

#[derive(Debug)]
struct Test {
    val: i32
}

fn main() {
    let a:&Test;
    let b = 32;

    let a = &Test {
        val: b
    };

    println!("{:?}", a.val);
}

使用变量遮蔽重新声明a后编译通过,原因在于变量遮蔽创建了新的引用变量,编译器可以重新推断生命周期:

  • 重新声明的let a是一个全新的变量,编译器会为它和右侧的临时值绑定匹配的生命周期;
  • 临时值Test { val: b }的生命周期会被延长到新a的生命周期结束(也就是main函数结束,因为后续要打印a.val);
  • 新a的引用始终指向存活的临时值,不存在悬垂引用问题,因此编译通过。

内容的提问来源于stack exchange,提问作者Abraham Tugalov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 22:20:39