ปัญหานี้ดูเหมือนจะบอกเป็นนัยว่าเป็นเพียงรายละเอียดการใช้งานเท่านั้น ( memcpy
เทียบกับ ???) แต่ฉันไม่พบคำอธิบายที่ชัดเจนเกี่ยวกับความแตกต่าง
ปัญหานี้ดูเหมือนจะบอกเป็นนัยว่าเป็นเพียงรายละเอียดการใช้งานเท่านั้น ( memcpy
เทียบกับ ???) แต่ฉันไม่พบคำอธิบายที่ชัดเจนเกี่ยวกับความแตกต่าง
คำตอบ:
Clone
ได้รับการออกแบบมาสำหรับการทำซ้ำโดยพลการ: การClone
ใช้งานสำหรับประเภทT
สามารถดำเนินการที่ซับซ้อนโดยพลการที่จำเป็นในการสร้างไฟล์T
. มันเป็นลักษณะปกติ (นอกเหนือจากการโหมโรง) ดังนั้นจึงต้องใช้เหมือนลักษณะปกติด้วยการเรียกใช้เมธอดเป็นต้น
Copy
ลักษณะแทนค่าที่สามารถทำซ้ำได้อย่างปลอดภัยผ่านmemcpy
: สิ่งที่ต้องการ reassignments และผ่านการโต้แย้งโดยมูลค่าให้กับฟังก์ชั่นมักจะmemcpy
s และอื่น ๆ สำหรับ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();
เพื่อหลีกเลี่ยงการย้ายนัยเราอย่างชัดเจนสามารถโทร
สิ่งนี้อาจก่อให้เกิดคำถามว่าจะบังคับย้ายประเภทที่ใช้ลักษณะการคัดลอกได้อย่างไร? . คำตอบสั้น ๆ : คุณทำไม่ได้ / ไม่สมเหตุสมผล