Rust报错‘returns a value referencing data owned by the current function’求助
解决Rust中返回Svg时的临时值引用错误
你遇到的错误核心是Rust的生命周期规则:draw函数中,self.point()创建的Point是临时值,生命周期只局限于当前函数内部。而to_svg()方法会获取这个临时Point的引用,存入Svg的items向量中。当函数结束时,临时Point被销毁,Svg里的引用就变成了悬空引用,Rust会直接拒绝这种不安全的行为。
解决方案1:将Point绑定到Figure生命周期
因为第三方库的Svg依赖引用,我们需要让被引用的Point拥有足够长的生命周期——至少和返回的Svg一致。最直接的办法是把Point作为成员存储在Figure结构体中,让它的生命周期和Figure实例绑定:
fn main() { let a = Figure { a: 3, point: Point { p: 3 }, }; println!("result: {}", a.draw().to_svg_str()); } struct Figure { a: i8, point: Point, // 添加Point成员,生命周期与Figure绑定 } pub struct Svg<'a> { pub items: Vec<&'a dyn ToSvgStr>, } pub trait ToSvg { fn to_svg(&self) -> Svg; } impl<T: ToSvgStr> ToSvg for T { fn to_svg(&self) -> Svg { Svg { items: vec![self] } } } pub trait ToSvgStr { fn to_svg_str(&self) -> String; } impl<'a> ToSvgStr for Svg<'a> { fn to_svg_str(&self) -> String { String::from("abc") } } struct Point { p: i8, } impl ToSvgStr for Point { fn to_svg_str(&self) -> String { format!("p = {}", self.p) } } impl Figure { fn draw(&self) -> Svg { self.point.to_svg() // 引用Figure成员的Point,生命周期与self一致 } }
解决方案2:用堆存储管理生命周期(不修改Figure结构)
如果不想改动Figure的结构,可以用Box将Point放到堆上,同时通过自定义结构体持有Box和Svg,确保堆上对象的生命周期覆盖Svg的使用周期:
fn main() { let a = Figure { a: 3 }; let owned_svg = a.draw(); println!("result: {}", owned_svg.get_svg().to_svg_str()); } struct Figure { a: i8, } pub struct Svg<'a> { pub items: Vec<&'a dyn ToSvgStr>, } pub trait ToSvg { fn to_svg(&self) -> Svg; } impl<T: ToSvgStr> ToSvg for T { fn to_svg(&self) -> Svg { Svg { items: vec![self] } } } pub trait ToSvgStr { fn to_svg_str(&self) -> String; } impl<'a> ToSvgStr for Svg<'a> { fn to_svg_str(&self) -> String { String::from("abc") } } struct Point { p: i8, } impl ToSvgStr for Point { fn to_svg_str(&self) -> String { format!("p = {}", self.p) } } // 自定义结构体,持有堆上的Point和对应的Svg struct OwnedSvg { _point: Box<dyn ToSvgStr>, svg: Svg<'static>, } impl OwnedSvg { fn from_point(point: Point) -> Self { let boxed = Box::new(point); let svg = Svg { items: vec![&*boxed as &dyn ToSvgStr] }; OwnedSvg { _point: boxed, svg } } fn get_svg(&self) -> &Svg { &self.svg } } impl Figure { fn point(&self) -> Point { Point { p: 3 } } fn draw(&self) -> OwnedSvg { OwnedSvg::from_point(self.point()) } }
内容的提问来源于stack exchange,提问作者Olivier Georg
相关产品推荐
相关产品推荐

