Rust中为什么返回局部变量引用不合法而本地创建的引用可合法返回?
Rust返回局部引用的合法性问题解析
核心规则:Rust的借用检查器会强制保证所有引用的生命周期都短于或等于被引用对象的生命周期,绝对不允许出现悬垂引用。
不合法代码的报错原因
fn produce_ref<'a>() -> &'a i32 { let v = 200; &v }
这段代码里的v是存储在函数栈帧上的局部变量,函数执行结束后栈帧会被销毁,v占用的内存会被系统回收。返回的&v是指向这块已经失效的栈内存的悬垂引用,完全违反借用规则,所以编译直接不通过。
两段合法代码的底层逻辑
两个合法示例的核心前提:数字字面量200是编译期确定的常量,会被存储在程序的静态存储区,生命周期为'static,也就是整个程序运行期间都会存在,不会随函数栈帧销毁而释放。
示例1合法性说明
fn produce_ref<'a>() -> &'a i32 { let v = &200; v }
这里&200拿到的是静态存储区中200的引用,本身带有'static生命周期,而'static生命周期长于任意的泛型生命周期'a,完全满足返回值的生命周期约束。
这里的局部变量v本身只是一个存了静态常量地址的栈上变量,你返回的是v存储的值(也就是静态常量的地址),不是对v本身的引用,不存在悬垂问题,自然合法。
示例2合法性说明
fn produce_ref<'a>() -> &'a i32 { let v = &200; &v }
这段代码看起来像是返回了栈上变量v的引用,实际触发了Rust的静态提升规则:
- 变量
v的类型是&'static i32,它的值是编译期就能确定的固定常量(指向静态区的200); - 当对这种编译期可确定的常量变量取引用时,Rust会把
v本身也提升到静态存储区存储,而不是存在函数栈上; - 最终你拿到的
&v是指向静态存储区中v的引用,生命周期为'static,满足返回值约束,编译自然通过。
内容的提问来源于stack exchange,提问作者0xedb
相关产品推荐
相关产品推荐

