Vấn đề này dường như ngụ ý rằng đó chỉ là một chi tiết triển khai ( memcpy
so 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 ( memcpy
so 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 ý: Clone
việc triển khai cho một kiểu T
có 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 memcpy
là, và như vậy cho Copy
cá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 .
Clone
là một bản sao sâu và Copy
là bản sao bóng tối không?
Clone
mở 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 Copy
loạ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 Copy
loạ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.
y
chuyển đi x
chứ 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 đó?
Copy
nó được triển khai cho các loại "giá rẻ", chẳng hạn như u8
trong 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ề Copy
vs Clone
là 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.