如何创建Trait对象副本以用于Rust本地计算?
问题分析与解决方案
你遇到的错误核心原因是:dyn CustomCollection属于无大小类型(编译时无法确定内存占用大小),而Box::new()要求传入的类型必须实现Sized trait——它需要先在栈上分配足够空间容纳实例,再转移到堆上,无大小类型无法满足这个要求。
要实现「创建Trait对象副本并修改」的需求,你需要给Trait添加对象安全的克隆方法,具体实现如下:
修正后的完整代码
#[derive(Clone)] struct Data { fields: Vec<f32> } trait CustomCollection { fn get_mut(&mut self) -> &mut [f32]; // 添加对象安全的克隆方法,返回Box包裹的Trait对象 fn clone_box(&self) -> Box<dyn CustomCollection>; } impl CustomCollection for Data { fn get_mut(&mut self) -> &mut [f32] { &mut self.fields } fn clone_box(&self) -> Box<dyn CustomCollection> { Box::new(self.clone()) } } fn copy(s: &mut dyn CustomCollection) { // 通过clone_box创建副本 let mut c: Box<dyn CustomCollection> = s.clone_box(); // 示例:修改副本内容 let slice = c.get_mut(); slice[0] = 10.0; println!("副本修改后第一个元素:{}", slice[0]); } fn main() { let mut d = Data{fields: vec![1f32, 2.0, 3.0]}; println!("原对象初始第一个元素:{}", d.fields[0]); copy(&mut d); println!("原对象未被修改,第一个元素还是:{}", d.fields[0]); }
关键说明
对象安全的克隆方法:
标准库的Clonetrait的clone()方法返回Self,对于dyn CustomCollection来说Self是无大小类型,不符合对象安全要求。因此手动添加clone_box()方法,返回Box<dyn CustomCollection>,确保可以在堆上存储Trait对象副本。派生Clone trait:
给Data添加#[derive(Clone)],让结构体本身支持克隆,再在clone_box()中调用self.clone()创建实例,最后用Box包裹成Trait对象。副本修改不影响原对象:
通过clone_box()创建的是完全独立的副本,修改副本的内容不会改动原对象,满足你「用修改后的副本计算,再基于结果修改原对象」的需求。
内容的提问来源于stack exchange,提问作者user3617992
相关产品推荐
相关产品推荐

