ปัญหานี้ดูเหมือนจะบอกเป็นนัยว่าเป็นเพียงรายละเอียดการใช้งานเท่านั้น ( memcpyเทียบกับ ???) แต่ฉันไม่พบคำอธิบายที่ชัดเจนเกี่ยวกับความแตกต่าง
ปัญหานี้ดูเหมือนจะบอกเป็นนัยว่าเป็นเพียงรายละเอียดการใช้งานเท่านั้น ( memcpyเทียบกับ ???) แต่ฉันไม่พบคำอธิบายที่ชัดเจนเกี่ยวกับความแตกต่าง
คำตอบ:
Cloneได้รับการออกแบบมาสำหรับการทำซ้ำโดยพลการ: การCloneใช้งานสำหรับประเภทTสามารถดำเนินการที่ซับซ้อนโดยพลการที่จำเป็นในการสร้างไฟล์T. มันเป็นลักษณะปกติ (นอกเหนือจากการโหมโรง) ดังนั้นจึงต้องใช้เหมือนลักษณะปกติด้วยการเรียกใช้เมธอดเป็นต้น
Copyลักษณะแทนค่าที่สามารถทำซ้ำได้อย่างปลอดภัยผ่านmemcpy: สิ่งที่ต้องการ reassignments และผ่านการโต้แย้งโดยมูลค่าให้กับฟังก์ชั่นมักจะmemcpys และอื่น ๆ สำหรับCopyประเภทคอมไพเลอร์เข้าใจว่ามันไม่จำเป็นที่จะต้องพิจารณาผู้ที่ย้าย
Cloneเป็นสำเนาลึกและCopyเป็นเงาคัดลอกได้หรือไม่
Cloneเปิดความเป็นไปได้ที่ประเภทอาจทำสำเนาลึกหรือตื้น: "ซับซ้อนโดยพลการ"
ความแตกต่างที่สำคัญคือการโคลนนั้นชัดเจน สัญกรณ์โดยปริยายหมายถึงการย้ายสำหรับ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()อาจเป็นวิธีการที่คุณเลือกโดยพลการในขณะที่การคัดลอกโดยปริยายจะเรียกใช้ a เสมอmemcpyไม่ใช่การclone(&self)ใช้งาน
yจะได้รับการย้ายไม่สำเนาของมันเช่นเดียวกับตัวอย่างออกความเห็นล่าสุดของคุณx w = vคุณจะระบุได้อย่างไร?
Copyมีขึ้นเพื่อใช้กับประเภท "ราคาถูก" เช่นu8ในตัวอย่าง ถ้าคุณเขียนชนิดหนามากที่คุณคิดว่าการย้ายจะมีประสิทธิภาพมากกว่าสำเนาทำให้มันไม่Copy Impl โปรดทราบว่าในกรณี u8 คุณจะไม่สามารถมีประสิทธิภาพมากขึ้นด้วยการย้ายเนื่องจากอย่างน้อยภายใต้ประทุนอาจมีสำเนาตัวชี้ซึ่งมีราคาแพงพอ ๆ กับสำเนา u8 อยู่แล้วดังนั้นทำไมต้องกังวล
Copyลักษณะมีผลกระทบต่อขอบเขตอายุการใช้งานโดยนัยของตัวแปรหรือไม่? ถ้าเป็นเช่นนั้นฉันคิดว่ามันน่าสนใจ
ตามคำตอบอื่น ๆ ที่กล่าวถึงแล้ว:
Copy เป็นนัยราคาไม่แพงและไม่สามารถนำมาใช้ใหม่ได้ (memcpy)Clone มีความชัดเจนอาจมีราคาแพงและอาจนำไปใช้ใหม่โดยพลการบางครั้งสิ่งที่ขาดหายไปในการอภิปรายเกี่ยวCopyกับ vs Cloneคือมันมีผลต่อวิธีการที่คอมไพเลอร์ใช้การเคลื่อนไหวเทียบกับสำเนาอัตโนมัติ ตัวอย่างเช่น:
#[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();เพื่อหลีกเลี่ยงการย้ายนัยเราอย่างชัดเจนสามารถโทร
สิ่งนี้อาจก่อให้เกิดคำถามว่าจะบังคับย้ายประเภทที่ใช้ลักษณะการคัดลอกได้อย่างไร? . คำตอบสั้น ๆ : คุณทำไม่ได้ / ไม่สมเหตุสมผล