Sự khác biệt giữa Copy và Clone là gì?


Câu trả lời:


115

Cloneđược thiết kế để sao chép tùy ý: Cloneviệc triển khai cho một kiểu Tcó thể thực hiện các thao tác phức tạp tùy ý được yêu cầu để tạo một kiểu mới T. Đó là một đặc điểm bình thường (không phải là ở khúc dạo đầu), và do đó, yêu cầu được sử dụng như một đặc điểm bình thường, với các lệnh gọi phương thức, v.v.

Các Copyđặc điểm đại diện cho các giá trị có thể được nhân đôi một cách an toàn thông qua memcpy: những thứ như reassignments và đi qua một cuộc tranh cãi bởi có giá trị đến một chức năng luôn memcpylà, và như vậy cho Copycác loại, trình biên dịch hiểu rằng nó không cần phải xem xét những động thái .


5
Tôi có thể hiểu như Clonelà một bản sao sâu và Copylà bản sao bóng tối không?
Djvu

11
Clonemở ra khả năng loại có thể thực hiện một bản sao sâu hoặc nông: "phức tạp tùy ý".
poolie

85

Sự khác biệt chính là nhân bản là rõ ràng. Ký hiệu ngầm có nghĩa là di chuyển cho một Copyloại không phải .

// 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.

Nhân tiện, mọi Copyloại cũng được yêu cầu Clone. Tuy nhiên, họ không bắt buộc phải làm điều tương tự! Đối với các loại của riêng bạn, .clone()có thể là một phương pháp tùy ý do bạn lựa chọn, trong khi sao chép ngầm sẽ luôn kích hoạt a memcpy, không phải việc clone(&self)triển khai.


1
Mát mẻ! Điều này làm rõ một câu hỏi thứ hai mà tôi có về việc liệu đặc điểm Nhân bản có cung cấp bản sao ngầm hay không. Hóa ra câu hỏi đó và câu hỏi này liên quan nhiều hơn tôi nghĩ. Cảm ơn!
user12341234

Trong ví dụ đầu tiên của bạn, giả sử bạn muốn ychuyển đi xchứ không phải bản sao của nó, giống như ví dụ được nhận xét cuối cùng của bạn w = v. Làm thế nào bạn sẽ xác định điều đó?
johnbakers

2
Bạn không thể và bạn cũng không, bởi vì Copynó được triển khai cho các loại "giá rẻ", chẳng hạn như u8trong ví dụ. Nếu bạn viết một loại khá nặng, mà bạn nghĩ rằng một thái này là hiệu quả hơn so với một bản sao, làm cho nó không impl Copy. Lưu ý rằng trong trường hợp u8, bạn không thể hiệu quả hơn với việc di chuyển, vì dưới mui xe, nó có thể ít nhất sẽ đòi hỏi một bản sao con trỏ - vốn đã đắt như một bản sao u8, vậy tại sao phải bận tâm.
mdup

Điều này có nghĩa là sự hiện diện của Copyđặc điểm có tác động đến phạm vi tồn tại của các biến không? Nếu vậy tôi nghĩ đó là điều đáng chú ý.
Brian Cain

7

Như đã được đề cập trong các câu trả lời khác:

  • Copy là ẩn, không tốn kém và không thể được thực hiện lại (memcpy).
  • Clone là rõ ràng, có thể tốn kém và có thể được triển khai lại tùy ý.

Điều đôi khi bị thiếu trong cuộc thảo luận về Copyvs Clonelà nó cũng ảnh hưởng đến cách trình biên dịch sử dụng di chuyển so với bản sao tự động. Ví dụ:

#[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);
}

Ví dụ đầu tiên ( PointCloneAndCopy) hoạt động tốt ở đây vì bản sao ngầm, nhưng ví dụ thứ hai ( PointCloneOnly) sẽ gặp lỗi khi sử dụng sau khi di chuyển:

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

Để tránh động thái ngầm, chúng tôi có thể gọi một cách rõ ràng let p2 = p1.clone();.

Điều này có thể đặt ra câu hỏi làm thế nào để thực hiện một bước di chuyển của một loại thực hiện đặc điểm Sao chép? . Câu trả lời ngắn gọn: Bạn không thể / không có ý nghĩa.


@Shepmaster Tôi đã xóa nó mặc dù tôi thấy nó dễ đọc hơn nhiều vì nó chứa mã hóa màu sắc đẹp của trình biên dịch Rust và tôi đặc biệt đảm bảo rằng tất cả các từ liên quan tìm kiếm cũng được chứa trong văn bản.
bluenote10
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.