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

为何两段Rust代码作用域表现不同?值未越界问题解析

为什么Rust中调用函数时有的值不会触发作用域问题?

先看你提到的两段示例代码:

报错的第一段代码

struct Owned {
    data: i32,
}

struct Borrowed<'a> {
    ref_data: &'a i32,
}

fn create_something() -> Borrowed<'_> {
    let o = Owned { data: 42 };
    Borrowed { ref_data: &o.data } // 报错:`o` does not live long enough
}

fn main() {
    let _b = create_something();
}

正常运行的第二段代码

struct Owned {
    data: i32,
}

struct Borrowed<'a> {
    ref_data: &'a i32,
}

fn create_something(other_bla: &Owned) -> Borrowed<'_> {
    Borrowed { ref_data: &other_bla.data }
}

fn main() {
    let o = Owned { data: 42 };
    let b = create_something(&o);
    println!("{}", b.ref_data); // 正常输出42
}

核心差异:引用指向的原始数据生命周期,而非参数本身的生命周期

  • 第一段里,create_something函数内的o是函数本地的Owned实例,它的生命周期只到函数执行完毕为止。函数结束后,o会被栈自动销毁,此时返回的Borrowed结构体里的引用就指向了一块已经被释放的内存——这就是Rust绝对不允许的“悬垂引用”,所以借用检查器直接报错拦截。

  • 第二段里,函数参数other_bla确实是栈上的一个引用副本,函数结束后这个副本会被弹出栈,但关键是:这个引用副本指向的原始数据是main函数里创建的o,o的生命周期覆盖了整个main函数的执行过程,包括create_something调用结束后b存在的时间段。返回的Borrowed结构体里的引用,本质上是直接指向main中的o.data,而不是栈上的other_bla参数。参数本身只是个指针副本,它的销毁完全不影响原始数据的存在。

说白了,Rust的借用检查器根本不关心作为参数的引用副本活多久,它只关心引用所指向的原始数据能不能活到引用被使用的时刻。只要原始数据的生命周期足够长,即使参数的副本被销毁,引用依然是安全有效的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 23:07:22