面试题答案
一键面试代码实现
#[derive(Clone)]
struct MyData {
data: Vec<String>,
}
fn main() {
let original = MyData {
data: vec!["hello".to_string(), "world".to_string()],
};
let cloned = original.clone();
println!("Original data: {:?}", original.data);
println!("Cloned data: {:?}", cloned.data);
}
clone
过程中Vec<String>
内部字符串所有权处理
在Rust中,String
类型在clone
时会进行深拷贝。当对MyData
实例调用clone
方法时,因为MyData
结构体的data
字段是Vec<String>
,clone
会遍历Vec
中的每个String
并调用其clone
方法。这意味着每个String
内部的堆上数据(字符串内容)都会被复制,original
和cloned
拥有各自独立的字符串数据,它们在堆上占据不同的内存空间。
不使用clone
,简单赋值的情况
如果尝试通过简单赋值来复制MyData
实例,例如:
struct MyData {
data: Vec<String>,
}
fn main() {
let original = MyData {
data: vec!["hello".to_string(), "world".to_string()],
};
let copied = original; // 这里发生移动
// println!("Original data: {:?}", original.data); // 这行会报错
println!("Copied data: {:?}", copied.data);
}
这样做会违反Rust的所有权规则中的独占性规则。在Rust中,当一个变量被赋值给另一个变量时,所有权会发生移动。original
将其对data
的所有权转移给了copied
,original
不再拥有对data
的有效引用。如果试图访问original.data
,编译器会报错,因为original
已经被移动,不再拥有合法的内存访问权。这确保了内存安全,防止悬空指针和重复释放内存等问题。