复制和克隆

虽然移动语义是默认的,但默认情况下会复制某些类型:

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:?}");
}
  • 赋值之后,p1p2 都拥有自己的数据。
  • 我们还可以使用 p1.clone() 显式复制数据。

复制和克隆是两码事:

  • 复制是指内存区域的按位复制,不适用于任意对象。
  • 复制不允许自定义逻辑(不同于 C++ 中的复制构造函数)。
  • 克隆是一种更通用的操作,也允许通过实现 Clone trait 来自定义行为。
  • 复制不适用于实现 Drop trait 的类型。

在上述示例中,请尝试以下操作:

  • struct Point 中添加 String 字段。由于 String 不属于 Copy 类型,因此无法编译。
  • derive 属性中移除 Copy。现在,编译器错误位于 p1println! 中。
  • 指出如果你改为克隆 p1,则可按预期运行。

如果学员问起 derive,只需说这是一种 在编译时生成 Rust 代码的方法。在这种情况下,系统会生成 CopyClone trait 的默认实现。