浅拷贝(Copy
)
- 语义:当一个类型实现了
Copy
特征,意味着在赋值或传递参数时,会直接复制栈上的数据。这种拷贝是廉价的,因为它不涉及堆上数据的复制,只是复制栈上的值。例如基本数据类型 i32
、f64
等默认实现了 Copy
特征。
- 示例:
let num1: i32 = 5;
let num2 = num1; // 这里是浅拷贝,直接在栈上复制值
println!("num1: {}, num2: {}", num1, num2);
- 适用场景:
- 对于简单的数据类型,如整数、浮点数、布尔值等,浅拷贝非常高效,因为它们占用空间小且不涉及堆上的复杂结构。
- 当传递或赋值大量简单数据时,浅拷贝可以避免性能开销,例如在函数参数传递
i32
类型的数组时。
深拷贝(Clone
)
- 语义:实现
Clone
特征时,会创建一个新的对象,并且会递归地复制堆上的数据。这意味着对于包含堆数据的复杂类型,会复制堆上的数据到新的内存位置,而不仅仅是栈上的指针。例如 String
、Vec<T>
等类型需要手动实现 Clone
特征(实际上编译器为它们自动生成了默认的 Clone
实现)。
- 示例:
let s1 = String::from("hello");
let s2 = s1.clone(); // 这里是深拷贝,复制了堆上的字符串数据
println!("s1: {}, s2: {}", s1, s2);
- 适用场景:
- 当你需要独立的对象副本,且对象包含堆上的数据,深拷贝是必要的。例如,你有一个自定义的结构体,其中包含
String
字段,如果你想要一个完全独立的结构体副本,就需要使用深拷贝。
- 当共享数据可能会被修改,并且你希望在修改时不影响原始数据时,深拷贝很有用。比如在多线程编程中,为了避免数据竞争,有时需要对数据进行深拷贝后再在不同线程中使用。