Vấn đề này dường như ngụ ý rằng đó chỉ là một chi tiết triển khai ( memcpyso với ???), nhưng tôi không thể tìm thấy bất kỳ mô tả rõ ràng nào về sự khác biệt.
Vấn đề này dường như ngụ ý rằng đó chỉ là một chi tiết triển khai ( memcpyso với ???), nhưng tôi không thể tìm thấy bất kỳ mô tả rõ ràng nào về sự khác biệt.
Câu trả lời:
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 .
Clonelà một bản sao sâu và Copylà bản sao bóng tối không?
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 ý".
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.
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 đó?
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.
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ú ý.
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.