2016-03-26 4 views
8

जंग के द्वारा संचालित दस्तावेज पर Rust Move Semantics पर दस्तावेज किए गए जंग के चाल अर्थशास्त्र का एक बड़ा उदाहरण है।जंग कैसे स्टैक वैरिएबल को स्थानांतरित करता है जो कॉपी करने योग्य नहीं हैं?

मुझे दोनों मामलों का मूलभूत समझ है। पहला यह है कि कैसे एक आदिम के पास एक नया उपनाम हो सकता है और मूल का उपयोग अभी भी किया जा सकता है क्योंकि अंतिम परिणाम i32Copy विशेषता का उपयोग करता है। यह मेरे लिए अच्छी समझ में आता है।

इसके अतिरिक्त, कई अच्छे कारणों से दूसरा उदाहरण कई उपनामों के संदर्भ में समझ में आता है जो ढेर पर i32 का संदर्भ देता है। जंग मालिकाना नियम लागू करती है और इसलिए मूल उपनाम का उपयोग नहीं किया जा सकता है कि एक नया बाध्यकारी बनाया गया है। यह डेटा-रेस, डबल फ्री इत्यादि को रोकने में मदद करता है।

लेकिन ऐसा लगता है कि एक तीसरा मामला है जिसके बारे में बात नहीं की जाती है। रस्ट आवंटित structs की चाल को कैसे कार्यान्वित करता है जो Copy विशेषता को लागू नहीं करता है? यह निम्न कोड के साथ दर्शाया गया है:

#[derive(Debug)] 
struct Employee{ 
    age: i32, 
} 

fn do_something(m: Employee){ 
    println!("{:?}", m); 
} 

fn main() { 
    let x = Employee { 
     age: 25, 
    }; 

    do_something(x); 

    //compiler error below because x has moved 
    do_something(x); 
} 

यह मुझे पता है: उपरोक्त मामले में, जंग ढेर पर Employee आवंटित करेगा। उपर्युक्त संरचना Copy विशेषता को लागू नहीं करती है और इसलिए किसी नए उपनाम को निर्दिष्ट किए जाने पर कॉपी नहीं की जाएगी। यह मेरे लिए बहुत भ्रमित है क्योंकि यदि Employee संरचना स्टैक पर आवंटित की जाती है और Copy विशेषता को लागू नहीं करती है, तो यह कहां/कैसे स्थानांतरित होती है? क्या यह शारीरिक रूप से do_something() के स्टैक फ्रेम में स्थानांतरित हो जाता है?

इस कन्डर्रम को समझाने में किसी भी मदद की सराहना की जाती है।

+1

क्या आप अपना उदाहरण सरलीकृत करना चाहते हैं? 'कर्मचारी 'संरचना को कम जटिल बनाने और कम से कम जीवनकाल को हटाने के लिए बहुत अच्छा होगा। 'संरचना कर्मचारी {आयु: i32}' उदाहरण के लिए पर्याप्त होगा। –

+0

@ लुकासकल्बर्टोड - हाँ मैंने उदाहरण को सरल बना दिया है। –

उत्तर

6

यह शारीरिक रूप से do_something() के ढेर फ्रेम में ले जाया गया हो रहा है?

हां। गैर-Copy प्रकार शारीरिक रूप से स्थानांतरित होते हैं जैसे कि Copy प्रकार हैं: memcpy के साथ। आप पहले ही समझ चुके हैं कि आदिम Copy-प्रकारों को नए स्थान (उदाहरण के लिए नया स्टैक फ्रेम) बाइट-बाय-बाइट में कॉपी किया गया है।

अब Box के इस कार्यान्वयन पर विचार करें:

struct Box<T> { 
    ptr: *const T, 
} 

जब आप

let b = Box::new(27i32); 
do_something(b); // `b` is moved into `do_something` 

तो एक i32 ढेर पर आवंटित किया जाता है है और Box कि ढेर आबंटित स्मृति के लिए कच्चे सूचक बचत होती है। ध्यान दें कि Box सीधे (कच्चे सूचक अंदर) सीधे ढेर पर है, ढेर पर नहीं! बस i32 ढेर पर है।

जब Box स्थानांतरित हो गया है, तो यह memcpy एड है, जैसा कि मैंने अभी कहा था। इसका मतलब है कि स्टैक सामग्री की प्रतिलिपि बनाई जाती है (!!) ... इस प्रकार केवल पॉइंटर को बाइट-बाय-बाइट कॉपी किया जाता है। i32 का दूसरा संस्करण नहीं है!

Copy और गैर-Copy प्रकारों के बीच कोई अंतर नहीं है जब शारीरिक रूप से चलने की बात आती है। केवल अंतर यह है कि संकलक उन प्रकारों पर विभिन्न नियम लागू करता है।

+4

माइनर नाइट: एआईयूआई, इस बात की कोई गारंटी नहीं है कि मूल्य * वास्तव में * स्थानांतरित हो जाएंगे, लेकिन अर्थशास्त्र ऐसे हैं कि आपको यह मानना ​​है कि वे हैं। उदाहरण के लिए, कंपाइलर बिट्स कॉपी करने से रोकने के लिए 'b' के संदर्भ को स्वीकार करने के लिए' do_something' को फिर से लिखने के लिए स्वतंत्र है। महत्वपूर्ण बात यह है कि कोड व्यवहार करता है * जैसे कि बिट्स चले गए थे। – Shepmaster

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