Copy和Clone有什么区别?

时间:2015-06-23 20:31:10

标签: rust

This issue似乎暗示它只是一个实现细节(memcpy vs ???),但我找不到任何明确的差异描述。

3 个答案:

答案 0 :(得分:91)

Clone专为任意重复而设计:类型Clone的{​​{1}}实现可以执行创建新T所需的任意复杂操作。这是一个正常的特征(除了在前奏中),因此需要像普通特征一样使用方法调用等。

T特征表示可以通过Copy安全复制的值:重新分配和将参数按值传递给函数的内容始终为memcpy s,因此{ {1}}类型,编译器理解它不需要考虑那些a move

答案 1 :(得分:58)

主要区别在于克隆是明确的。隐式表示法意味着移动非Copy类型。

// u8 implements Copy
let x: u8 = 123;
let y = x;
// x can still be used
println!("x={}, y={}", x, y);

// Vec<u8> implements Clone, but not Copy
let v: Vec<u8> = vec![1, 2, 3];
let w = v.clone();
//let w = v // This would *move* the value, rendering v unusable.

顺便说一下,每个Copy类型也必须是Clone。但是,他们不需要做同样的事情!对于您自己的类型,.clone()可以是您选择的任意方法,而隐式复制将始终触发memcpy,而不是clone(&self)实现。

答案 2 :(得分:4)

其他答案已经涵盖了

  • Copy是隐式的,廉价的,并且无法重新实现(memcpy)。
  • Clone是明确的,可能会很昂贵,并且可能会任意重新实现。

CopyClone的讨论中有时会缺少的一点是,它还影响编译器使用移动与自动副本的方式。例如:

#[derive(Debug, Clone, Copy)]
pub struct PointCloneAndCopy {
    pub x: f64,
}

#[derive(Debug, Clone)]
pub struct PointCloneOnly {
    pub x: f64,
}

fn test_copy_and_clone() {
    let p1 = PointCloneAndCopy { x: 0. };
    let p2 = p1; // because type has `Copy`, it gets copied automatically.
    println!("{:?} {:?}", p1, p2);
}

fn test_clone_only() {
    let p1 = PointCloneOnly { x: 0. };
    let p2 = p1; // because type has no `Copy`, this is a move instead.
    println!("{:?} {:?}", p1, p2);
}

由于隐式副本,第一个示例(PointCloneAndCopy)在这里工作正常,但是第二个示例(PointCloneOnly)在移动后使用时会出错:

error[E0382]: borrow of moved value: `p1`
  --> src/lib.rs:20:27
   |
18 |     let p1 = PointCloneOnly { x: 0. };
   |         -- move occurs because `p1` has type `PointCloneOnly`, which does not implement the `Copy` trait
19 |     let p2 = p1;
   |              -- value moved here
20 |     println!("{:?} {:?}", p1, p2);
   |                           ^^ value borrowed here after move

为避免隐式移动,我们可以显式调用let p2 = p1.clone();

这可能会引起how to force a move of a type which implements the Copy trait?的问题。简短的答案:你不可能/没有道理。