कॉपी और क्लोन में क्या अंतर है?


128

इस समस्या का अर्थ यह है कि यह केवल एक कार्यान्वयन विवरण है ( memcpyबनाम ???), लेकिन मुझे मतभेदों का कोई स्पष्ट विवरण नहीं मिल सकता है।


Rust के सोर्स कोड की प्रासंगिक व्याख्या है
duan

जवाबों:


115

Cloneको मनमाने ढंग से दोहराव के लिए डिज़ाइन किया गया है: एक Cloneप्रकार के लिए एक कार्यान्वयन Tएक नया बनाने के लिए आवश्यक रूप से जटिल परिचालन कर सकता है T। यह एक सामान्य लक्षण है (प्रस्तावना में होने के अलावा), और इसलिए सामान्य कॉल की तरह, कॉल आदि के साथ इसका उपयोग करने की आवश्यकता होती है।

Copyविशेषता मान जो सुरक्षित रूप से के माध्यम से दोहराया जा सकता है का प्रतिनिधित्व करता है memcpy: reassignments कर रहे हैं और एक कार्य करने के लिए दर-मूल्य एक तर्क गुजर हमेशा की तरह बातें memcpyहै, और इतने के लिए Copyप्रकार, संकलक समझता है कि यह उन पर विचार करने की जरूरत नहीं है एक चाल


5
क्या मैं समझ सकता हूं कि Cloneएक गहरी-प्रति है, और Copyछाया-प्रति है?
Djvu

11
Cloneइस संभावना को खोलता है कि प्रकार या तो गहरी या उथली प्रतिलिपि कर सकता है: "मनमाने ढंग से जटिल"।
पूलि

85

मुख्य अंतर यह है कि क्लोनिंग स्पष्ट है। अव्यय संकेतन का अर्थ है गैर- 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()अपनी पसंद का एक मनमाना तरीका हो सकता है, जबकि अंतर्निहित नकल हमेशा एक ट्रिगर होगी memcpy, clone(&self)कार्यान्वयन नहीं ।


1
ठंडा! यह एक द्वितीयक प्रश्न को स्पष्ट करता है, जिसके बारे में मेरे पास था कि क्या क्लोन विशेषता अंतर्निहित नकल प्रदान करती है। उस सवाल को टाल दिया और यह एक जितना मैंने सोचा था उससे अधिक संबंधित थे। धन्यवाद!
user12341234

अपने पहले उदाहरण में, मान लीजिए कि आप yएक स्थानांतरित करना चाहते हैं x, इसकी एक प्रति नहीं है, जैसे कि आपके अंतिम उदाहरण के साथ w = v। आप इसे कैसे निर्दिष्ट करेंगे?
जॉन्बेकर्स

2
आप नहीं कर सकते, और आप नहीं करते हैं, क्योंकि Copy"सस्ते" प्रकारों के लिए लागू किया जाना है, जैसे u8कि उदाहरण में। यदि आप एक बहुत भारी वजन लिखते हैं, जिसके लिए आपको लगता है कि एक प्रतिलिपि की तुलना में एक चाल अधिक कुशल है, तो इसे निहित न करेंCopy । ध्यान दें कि u8 के मामले में, आप संभवतः एक चाल के साथ अधिक कुशल नहीं हो सकते हैं, क्योंकि हुड के तहत यह संभवतः कम से कम एक पॉइंटर कॉपी में प्रवेश करेगा - जो पहले से ही u8 कॉपी के रूप में महंगा है, इसलिए परेशान क्यों है।
mdup

क्या इसका मतलब यह है कि Copyचर की उपस्थिति का वैरिएबल के अंतर्निहित आजीवन दायरे पर प्रभाव पड़ता है? यदि ऐसा है तो मुझे लगता है कि यह उल्लेखनीय है।
ब्रायन कैन

7

जैसा कि पहले से ही अन्य उत्तरों द्वारा कवर किया गया है:

  • Copy निहित है, सस्ती है, और फिर से लागू नहीं किया जा सकता (मेमसीपी)।
  • Clone स्पष्ट है, महंगा हो सकता है, और मनमाने ढंग से फिर से लागू हो सकता है।

कभी-कभी Copyबनाम की चर्चा में जो चीज गायब होती 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();

यह प्रश्न उठा सकता है कि एक प्रकार की चाल को कैसे लागू किया जाए जो प्रतिलिपि विशेषता को लागू करता है? । संक्षिप्त उत्तर: आप समझ नहीं सकते / नहीं बना सकते।


@ शेमेस्टर ने मुझे इसे हटा दिया हालांकि मुझे यह बहुत अधिक पठनीय लगता है क्योंकि इसमें रस्ट कंपाइलर का अच्छा रंग कोडिंग है और मैंने विशेष रूप से यह सुनिश्चित किया है कि सभी खोज प्रासंगिक शब्द भी पाठ में निहित हैं।
bluenote10
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.