复制和克隆
虽然移动语义是默认的,但默认情况下会复制某些类型:
fn main() { let x = 42; let y = x; println!("x: {x}"); println!("y: {y}"); }
这些类型实现了 Copy
trait。
你可以选择自己的类型来使用复制语义:
#[derive(Copy, Clone, Debug)] struct Point(i32, i32); fn main() { let p1 = Point(3, 4); let p2 = p1; println!("p1: {p1:?}"); println!("p2: {p2:?}"); }
- 赋值之后,
p1
和p2
都拥有自己的数据。 - 我们还可以使用
p1.clone()
显式复制数据。
复制和克隆是两码事:
- 复制是指内存区域的按位复制,不适用于任意对象。
- 复制不允许自定义逻辑(不同于 C++ 中的复制构造函数)。
- 克隆是一种更通用的操作,也允许通过实现
Clone
trait 来自定义行为。 - 复制不适用于实现
Drop
trait 的类型。
在上述示例中,请尝试以下操作:
- 在
struct Point
中添加String
字段。由于String
不属于Copy
类型,因此无法编译。 - 从
derive
属性中移除Copy
。现在,编译器错误位于p1
的println!
中。 - 指出如果你改为克隆
p1
,则可按预期运行。
如果学员问起 derive
,只需说这是一种 在编译时生成 Rust 代码的方法。在这种情况下,系统会生成 Copy
和 Clone
trait 的默认实现。