Rust如何为结构体可变属性设置默认值并解决临时引用报错
问题原因
你在new函数内部创建的临时值342存放在当前函数的栈帧上,函数执行结束后栈帧会被回收,该临时值也会随之销毁。将它的可变引用存入要返回的MyStruct实例会产生悬垂引用,Rust的借用检查器会直接阻止这种不安全操作,因此抛出E0515错误。
解决方案
根据你的实际业务需求,可以选择以下三种方案:
方案1:改为持有值所有权(最推荐)
如果不需要通过MyStruct修改外部的usize变量,直接将结构体字段改为持有usize所有权即可,完全规避生命周期问题:
pub struct MyStruct { param: usize, } impl MyStruct { pub fn new(param: Option<usize>) -> Result<Self, Error> { let tmp = param.unwrap_or(342); Ok(Self { param: tmp }) } }
方案2:用枚举包装两种存储形式(保留修改外部变量能力)
如果确实需要支持修改外部传入的usize变量,可以自定义枚举同时支持外部可变引用和内部持有值两种场景,再实现Deref/DerefMut让它可以和普通usize引用一样使用:
use std::ops::{Deref, DerefMut}; enum Param<'a> { ExternalRef(&'a mut usize), Owned(usize), } impl<'a> Deref for Param<'a> { type Target = usize; fn deref(&self) -> &Self::Target { match self { Param::ExternalRef(r) => r, Param::Owned(o) => o, } } } impl<'a> DerefMut for Param<'a> { fn deref_mut(&mut self) -> &mut Self::Target { match self { Param::ExternalRef(r) => r, Param::Owned(o) => o, } } } pub struct MyStruct<'a> { param: Param<'a>, } impl<'a> MyStruct<'a> { pub fn new(param: Option<&'a mut usize>) -> Result<Self, Error> { let tmp = match param { Some(p) => Param::ExternalRef(p), None => Param::Owned(342), }; Ok(Self { param: tmp }) } }
方案3:使用静态变量(不推荐)
如果确定默认值可以全局共享,也可以用静态变量存储默认值,避开栈内存回收问题,但该方案存在全局共享修改风险,多线程场景下还需要加同步锁,非必要不使用:
static mut DEFAULT_PARAM: usize = 342; impl<'a> MyStruct<'a> { pub fn new(param: Option<&'a mut usize>) -> Result<Self, Error> { let tmp = param.unwrap_or(unsafe { &mut DEFAULT_PARAM }); Ok(Self { param: tmp }) } }
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

