2016-01-03 5 views
8

अगर मैं दो बार एक टुकड़ा से अधिक पुनरावृति करने की कोशिश, it works fine:मैं एक टुकड़ा दो बार फिर से क्यों कर सकता हूं, लेकिन वेक्टर नहीं?

let a = &[1, 2, 3]; 
for i in a { 
    println!("{}", i); 
} 
for i in a {   // works fine 
    println!("{}", i); 
} 

लेकिन अगर मैं it fails दो बार एक वेक्टर से अधिक पुनरावृति करने का प्रयास:

let a = vec![1, 2, 3]; 
for i in a { 
    println!("{}", i); 
} 
for i in a {   // error: use of moved value: `a` 
    println!("{}", i); 
} 

मुझे लगता है कि IntoIterator विशेषता द्वारा self लेता है मूल्य, तो यह मुझे समझ में आता है कि दूसरा उदाहरण विफल रहता है। लेकिन पहला उदाहरण सफल क्यों होता है?

+1

pedantically, पहले मामले में, 'A' के प्रकार नहीं वास्तव में एक टुकड़ा है, यह लंबाई 3. की ​​एक सरणी के लिए एक संदर्भ है हालांकि, * deref coercions * एक सरणी के लिए एक संदर्भ में कार्य करने की अनुमति है ज्यादातर मामलों में एक टुकड़ा की तरह। स्पष्टीकरण के लिए – Shepmaster

+0

@ शेमपस्टर धन्यवाद। क्या मैं यह सोचने में सही हूं कि पहले उदाहरण में 'ए' का प्रकार' &[i32; 3] है, जबकि एक टुकड़ा 'और [i32]' होगा? साथ ही, [यहां सूचीबद्ध सूची] (https://doc.rust-lang.org/std/ops/trait.Deref.html) में दिखाई देने वाले डेरफ जबरदस्ती है, या यह अधिक जादुई है? –

+1

हां, वे प्रकार होंगे। मैंने थोड़ा सा झूठ बोला, यह एक dereference से थोड़ा अधिक जादुई है [https://github.com/rust-lang/rust/issues/29993), यह एक * जबरदस्ती * है। दस्तावेज़ों को जल्द ही ठीक से अद्यतन किया जाएगा। – Shepmaster

उत्तर

12

जैसे तुमने कहा, आप इसे पूछा अधिक तेज़ी से दोहराने में बात ले, और IntoIterator::into_iter के माध्यम से इसे पारित वास्तविक इटरेटर मूल्य का उत्पादन करने से for काम करता है। जैसा कि आपने कहा, into_iter विषय विषय द्वारा विषय लेता है।

इसलिए, जब आप एक Vector सीधे से अधिक पुनरावृति करने की कोशिश, आप पूरी सदिश पारित इसका मतलब है, मूल्य, अपने IntoIterator कार्यान्वयन में, इस प्रकार की प्रक्रिया में वेक्टर लेने से। यही कारण है कि आप एक वेक्टर पर दो बार फिर से नहीं जा सकते हैं: इसे पहली बार फिर से उपभोग कर लेते हैं, जिसके बाद यह अस्तित्व में नहीं आता है।

हालांकि, स्लाइस अलग हैं: एक टुकड़ा अपने डेटा के लिए एक अपरिवर्तनीय, उधार सूचक है; अपरिवर्तनीय, उधारकर्ता पॉइंटर्स को स्वतंत्र रूप से कॉपी किया जा सकता है। इसका मतलब है कि IntoIterator अपरिवर्तनीय स्लाइस के लिए बस डेटा उधार लेता है और इसका उपभोग नहीं करता है (नहीं कि यह हो सकता है)। या, इसे किसी अन्य तरीके से देखने के लिए, IntoIterator कार्यान्वयन बस स्लाइस की प्रतिलिपि ले रहा है, जबकि आप Vec कॉपी नहीं कर सकते हैं।

यह ध्यान दिया जाना चाहिए कि आप Vecपर बिना किसी उधार पर इसे उपभोग कर उपभोग कर सकते हैं। यदि आप documentation for Vec चेक करते हैं, तो आप ध्यान दें कि Vec<T>, &Vec<T> और &mut Vec<T> के लिए IntoIterator के कार्यान्वयन की सूची है।

let mut a: Vec<i32> = vec![1, 2, 3]; 

for i in &a {   // iterate immutably 
    let i: &i32 = i; // elements are immutable pointers 
    println!("{}", i); 
} 

for i in &mut a {  // iterate mutably 
    let i: &mut i32 = i;// elements are mutable pointers 
    *i *= 2; 
} 

for i in a {   // iterate by-value 
    let i: i32 = i;  // elements are values 
    println!("{}", i); 
} 

// `a` no longer exists; it was consumed by the previous loop. 
+0

यह बहुत उपयोगी था, धन्यवाद। क्या मैं इसे इस तरह सारांशित कर सकता हूं? 1) यदि किसी प्रकार को 'कॉपी' प्राप्त होता है, तो आप उसे "मूल्य द्वारा" फ़ंक्शन के माध्यम से पास कर सकते हैं और फिर भी इसे बाद में उपयोग कर सकते हैं, और 2) कुछ जादुई तरीके से, स्लाइस 'कॉपी' लागू करते हैं। –

+2

@ जैकओ'कोनर, यह मूल रूप से सही है, सिवाय इसके कि उस स्लाइस में वास्तव में कुछ भी जादुई नहीं है 'कॉपी' लागू करें। एक टुकड़ा अनिवार्य रूप से एक अपरिवर्तनीय संदर्भ है, और अपरिवर्तनीय संदर्भ स्वाभाविक रूप से 'प्रतिलिपि' हैं। –

संबंधित मुद्दे

 संबंधित मुद्दे