面试题答案
一键面试误区1:未正确处理成员的Clone
- 说明:如果结构体包含的成员类型未实现
Clone
,但在impl Clone
时没有正确处理,会导致编译错误。 - 示例:
struct Inner {
data: i32
}
// 这里Inner没有实现Clone
struct Outer {
inner: Inner
}
// 错误的实现,因为Inner未实现Clone
// impl Clone for Outer {
// fn clone(&self) -> Self {
// Self {
// inner: self.inner
// }
// }
// }
正确做法是要么让 Inner
实现 Clone
,要么在 Outer
的 Clone
实现中以其他合适方式处理 Inner
,比如重新创建一个新的 Inner
。
误区2:浅拷贝问题
- 说明:当结构体包含指针类型成员时,简单的成员复制可能导致浅拷贝,多个克隆对象共享同一块数据,修改一个会影响其他。
- 示例:
struct StringWrapper {
data: String
}
impl Clone for StringWrapper {
fn clone(&self) -> Self {
Self {
data: self.data.clone()
}
}
}
fn main() {
let s1 = StringWrapper { data: "hello".to_string() };
let s2 = s1.clone();
s2.data.push_str(", world");
println!("s1: {}, s2: {}", s1.data, s2.data);
}
如果 StringWrapper
的 Clone
实现没有对 String
进行深拷贝(即 self.data.clone()
),而是直接赋值 self.data
,那么 s1
和 s2
中的 data
会指向同一块内存,修改 s2.data
就会影响 s1.data
。
误区3:忽略了派生的Clone
- 说明:对于简单的结构体,Rust 可以自动派生
Clone
,但开发者可能会在不需要手动实现的情况下,手动实现了一个错误的Clone
版本。 - 示例:
struct Point {
x: i32,
y: i32
}
// 不需要手动实现,因为可以派生
// impl Clone for Point {
// fn clone(&self) -> Self {
// Self {
// x: self.x + 1, // 错误的实现,改变了x的值
// y: self.y
// }
// }
// }
// 正确做法,使用派生
#[derive(Clone)]
struct Point {
x: i32,
y: i32
}
这样通过 #[derive(Clone)]
,Rust 会为 Point
结构体生成正确的 Clone
实现。