为何Rust中call3返回局部变量引用可编译,call1、call2却失败?
为何Rust中call3可编译通过,call1与call2却报"cannot return reference to temporary value"错误?
先看给出的代码示例:
struct Demo(i32); impl Demo { fn new() -> Self { Self(22) } } // 编译错误:cannot return reference to temporary value fn call1<'a>() -> &'a Demo { let a = Demo(3); &a } // 编译错误:cannot return reference to temporary value fn call2<'a>() -> &'a Demo{ &Demo::new() } // 编译成功! fn call3<'a>() -> &'a Demo { &Demo(34) }
接下来逐个分析原因:
call1编译失败的原因:
函数内的局部变量a在栈上分配,函数执行完毕后栈帧销毁,a占用的内存会被释放。返回&a相当于返回指向已释放内存的悬空引用,Rust的借用检查器会直接拦截这种不安全行为,因此抛出编译错误。call2编译失败的原因:
Demo::new()创建的临时Demo实例,生命周期仅局限于当前表达式范围内。函数准备返回引用时,这个临时值已经被销毁,同样会产生悬空引用,编译器因此拒绝通过编译。call3编译成功的原因:
直接使用结构体字面量Demo(34)并取引用时,Rust编译器会触发特殊优化:由于Demo是不包含任何非静态引用的类型,编译器会自动将这个临时实例提升到静态内存区,赋予它'static生命周期(贯穿整个程序运行期间)。函数返回的&'a Demo中,生命周期参数'a会被自动推断为'static('static是所有生命周期的超集,能满足任意'a的约束),因此这个引用始终有效,不会出现悬空问题,最终可以成功编译。
内容的提问来源于stack exchange,提问作者Hsu Jason
相关产品推荐
相关产品推荐

