Rust में स्व-संदर्भित संरचनाएँ: चरण-दर-चरण ट्यूटोरियल

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

Rust आपको स्वयं पर संदर्भ संग्रहीत करने की अनुमति क्यों नहीं देता: उदाहरणों के साथ समझें

\n\n

एक स्थिति की कल्पना करें: आप Rust में एक प्रोग्राम लिख रहे हैं, और आपको एक ऐसी संरचना बनाने की आवश्यकता है जो कुछ डेटा संग्रहीत करती है, साथ ही उसी डेटा का एक संदर्भ भी। तार्किक है, है ना? बिल्कुल! लेकिन Rust कंपाइलर अचानक एक त्रुटि देता है, और आप हैरान रह जाते हैं। परिचित लगता है? यह प्रश्न Stack Overflow पर सबसे लोकप्रिय प्रश्नों में से एक है (हज़ारों बार देखा गया), और आज हम इसे शुरू से अंत तक समझेंगे।

\n\n

इस चरण-दर-चरण ट्यूटोरियल में, हम न केवल यह समझेंगे कि Rust में एक ही संरचना में मान और संदर्भ क्यों नहीं रख सकते, बल्कि इस सीमा को सुरक्षित तरीकों से पार करना भी सीखेंगे। चलिए शुरू करते हैं!

\n\n

समस्या: एक भोली कोशिश

\n\n

मान लीजिए, हम एक ऐसी संरचना बनाना चाहते हैं जो एक स्ट्रिंग और उसका पहला अक्षर (पहले वर्ण का संदर्भ) संग्रहीत करती है। कोड में यह इस तरह दिखता है:

\n\n
struct MyStruct {\n    data: String,\n    first_char: &str,  // data का संदर्भ\n}\n\nfn main() {\n    let s = String::from("Hello");\n    let first = &s[0..1];  // पहले वर्ण का संदर्भ\n    \n    let my_struct = MyStruct {\n        data: s,\n        first_char: first,  // संदर्भ को सहेजने का प्रयास\n    };\n}\n
\n\n

कंपाइलर एक त्रुटि देता है जो कई शुरुआती लोगों को भ्रमित करती है। आइए समझें कि वास्तव में क्या गलत हुआ।

\n\n

Rust स्व-संदर्भित संरचनाओं को क्यों प्रतिबंधित करता है?

\n\n

समस्या की जड़ Rust की ownership (स्वामित्व) और borrowing (उधार) प्रणाली में है। जब आप मान s को data क्षेत्र में move (स्थानांतरित) करते हैं, तो यह भौतिक रूप से मेमोरी में एक नए स्थान पर कॉपी हो जाता है। संदर्भ first अभी भी पुराने पते की ओर इशारा करता है, जो अब अमान्य है।

\n\n

Rust में, प्रत्येक संदर्भ अपने पूरे अस्तित्व के दौरान मान्य होना चाहिए। Rust स्व-संदर्भित संरचनाएँ इस नियम का उल्लंघन करती हैं, क्योंकि संदर्भ और मान एक ही ऑब्जेक्ट में रहते हैं, और संरचना के स्थानांतरित होने पर संदर्भ dangling reference (लटकता हुआ संदर्भ) बन जाता है।

\n\n

अंदर क्या होता है?

\n\n

जब आप ऐसा कोड लिखते हैं:

\n\n
let s = String::from("Hello");\nlet first = &s[0..1];\nlet my_struct = MyStruct { data: s, first_char: first };\n
\n\n

निम्नलिखित होता है:

\n
    \n
  1. s के पास हीप में स्ट्रिंग "Hello" का स्वामित्व है।
  2. \n
  3. first — इस स्ट्रिंग के एक भाग का संदर्भ है।
  4. \n
  5. संरचना बनाते समय data: s — स्ट्रिंग का स्वामित्व संरचना को स्थानांतरित हो जाता है। स्ट्रिंग मेमोरी में स्थानांतरित हो सकती है।
  6. \n
  7. संदर्भ first अभी भी पुराने पते की ओर इशारा करता है — यह एक dangling reference (लटकता हुआ संदर्भ) है। Rust इसे अनुमति नहीं दे सकता।
  8. \n
\n\n

Rust का Borrow checker इस संभावित असुरक्षा को देखता है और संकलन चरण में कोड को ब्लॉक कर देता है। यह कोई बग नहीं, बल्कि एक विशेषता है जो रनटाइम में कई समस्याओं से बचाती है।

\n\n

वास्तविक परिदृश्य जहाँ स्व-संदर्भित संरचनाओं की आवश्यकता होती है

\n\n

प्रतिबंध के बावजूद, ऐसी संरचनाएँ उपयोगी हो सकती हैं। यहाँ विशिष्ट मामले हैं:

\n\n
    \n
  • पार्सर और AST: जब ट्री के नोड एक-दूसरे को संदर्भित करते हैं।
  • \n
  • गेम इंजन: ऐसी संस्थाएँ जिनमें अपने घटकों के संदर्भ होते हैं।
  • \n
  • नेटवर्क प्रोटोकॉल: आंतरिक पॉइंटर्स वाले बफ़र।
  • \n
  • प्लगइन सिस्टम: जब कोई ऑब्जेक्ट अपने कॉन्फ़िगरेशन का संदर्भ रखता है।
  • \n
\n\n

अच्छी खबर: इस सीमा को पार करने के सुरक्षित तरीके हैं!

\n\n

समाधान 1: संदर्भों के बजाय इंडेक्स का उपयोग करना (सबसे आसान तरीका)

\n\n

सबसे आसान और सुरक्षित तरीका है कि संदर्भ के बजाय इंडेक्स या कुंजी संग्रहीत करें। &str के बजाय usize (पहले वर्ण की स्थिति) संग्रहीत करें।

\n\n
struct MyStruct {\n    data: String,\n    first_char_index: usize,  // संदर्भ के बजाय स्थिति संग्रहीत करें\n}\n\nimpl MyStruct {\n    fn first_char(&self) -> &                

ब्लॉग

पुस्तक अनुशंसाएँ