面试题答案
一键面试浅拷贝测试
- 实现
Clone
特质:为Inner
和Outer
结构体实现Clone
特质,使它们默认实现浅拷贝。#[derive(Clone)] struct Inner { sub_data: String, } #[derive(Clone)] struct Outer { inner_vec: Vec<Inner>, data: i32, }
- 编写测试:在测试函数中,创建一个
Outer
实例,进行克隆,并检查克隆后的实例和原实例的内存地址。#[cfg(test)] mod tests { use super::*; #[test] fn test_shallow_clone() { let original = Outer { inner_vec: vec![Inner { sub_data: "test".to_string() }], data: 42, }; let cloned = original.clone(); assert_eq!(original.data, cloned.data); assert_eq!(original.inner_vec.len(), cloned.inner_vec.len()); // 浅拷贝,内部字符串的指针相同 assert!(std::ptr::eq( original.inner_vec[0].sub_data.as_ptr(), cloned.inner_vec[0].sub_data.as_ptr() )); } }
深拷贝测试
- 实现
Clone
特质(深拷贝):手动实现Clone
特质来进行深拷贝,对于Inner
结构体,需要对sub_data
进行深拷贝。struct Inner { sub_data: String, } impl Clone for Inner { fn clone(&self) -> Inner { Inner { sub_data: self.sub_data.clone(), } } } struct Outer { inner_vec: Vec<Inner>, data: i32, } impl Clone for Outer { fn clone(&self) -> Outer { Outer { inner_vec: self.inner_vec.clone(), data: self.data, } } }
- 编写测试:同样创建一个
Outer
实例,进行克隆,并检查克隆后的实例和原实例的内存地址。#[cfg(test)] mod tests { use super::*; #[test] fn test_deep_clone() { let original = Outer { inner_vec: vec![Inner { sub_data: "test".to_string() }], data: 42, }; let cloned = original.clone(); assert_eq!(original.data, cloned.data); assert_eq!(original.inner_vec.len(), cloned.inner_vec.len()); // 深拷贝,内部字符串的指针不同 assert!(!std::ptr::eq( original.inner_vec[0].sub_data.as_ptr(), cloned.inner_vec[0].sub_data.as_ptr() )); } }
可能遇到的陷阱及解决方案
- 默认浅拷贝问题:如果只依赖
#[derive(Clone)]
,可能得到浅拷贝,导致修改克隆实例的内部数据影响原实例。解决方案是手动实现Clone
特质进行深拷贝。 - 递归结构体:如果结构体存在递归嵌套,实现深拷贝时要小心递归调用,防止栈溢出。可以使用迭代方法或者
Rc
/RefCell
等智能指针来处理递归结构。 - 未实现
Clone
特质:如果自定义结构体的成员没有实现Clone
特质,编译器会报错。确保所有成员都实现Clone
特质,或者手动实现父结构体的Clone
特质来处理成员的拷贝。