Please enable Javascript to view the contents

[Rust Std Trait] Copy/Clone 初见

 ·  ☕ 2 分钟

前言

    Copy 作为能够影响编译器行为的 trait 对我们理解 Rust 基础有着重要作用,而 Clone 是我们作为搬砖工人能够自定义复制行为的 trait。本篇文章将会用最短的篇幅覆盖 Copy 和 Clone 的主要知识点。

至关重要的 Copy trait

    提问,以下代码为何 print1 行不报错:

1
2
3
4
5
6
7
8
extern crate hello_rust;

fn main() {
    let num1 = 1i32;
    let num2 = num1;
    println!("{}", num1); // print 1
    println!("{}", num2); // print 2
}

其实这里就需要理解 Copy trait 在当中起的作用。如果一个类型实现了 Copy trait,那么它在变量绑定,函数参数传递,函数返回值的场景等场景下都是 copy 语义,而不是默认的 move 语义。上面的例子因为 Rust 已经帮你把 i32 的 Copy trait 实现好了,所以才以 Copy 语义使用。所以,即使是我们自己定义的类型,只要实现了 Copy trait 也会变成 Copy 语义:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
extern crate hello_rust;

#[derive(Debug, Copy, Clone)]
struct TA(i32);

fn main() {
    let t1 = TA(1);
    let t2 = t1;
    println!("{:?}", t1); // print 3
    println!("{:?}", t2); // print 4
}

    Copy trait 对类型有一定要求,如果想让我们的自定义类型实现 Copy trait,那么它的所有成员都必须是实现了 Copy trait 的。标准库除常规 impl 的类型外还特别提及以下类型也是 Copy 的:

  • 函数/函数指针
  • 元素为 Copy 的数组和元组
  • 闭包(不捕获或者捕获 Copy)

能够自定义的 Clone trait

     Copy 的行为我们是无法控制的。如果我们想自定义例如“类型深复制”的行为,可以实现 Clone trait。Copy 是隐式改变编译器的行为,而 Clone 需要我们显式调用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
extern crate hello_rust;

#[derive(Debug, Clone)]
struct CT {
    field1: i32,
    field2: bool,
}

fn main() {
    let ct = CT {
        field1: 1,
        field2: false,
    };

    println!("{:?}", ct.clone());
}

如果我们想自定义 Clone trait 的行为可以手动实现 trait,Rust 不会限制你的具体自定义实现,不过对于同时还要实现 Copy trait 的类型都确保 Clone 和 Copy 代表的语义相同。可以直接在 derive 中二连使用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
impl Clone for CT {
    fn clone(&self) -> Self {
        *self
    }
}
// or
#[derive(Debug, Copy, Clone)]
struct CT {
    field1: i32,
    field2: bool,
}
分享

saberuster
作者
saberuster
一个喜欢编程和折腾的追风少年