मुख्य सामग्री पर जाएं
मॉड्यूल 6 · पाठ 2 का 2पाठ्यक्रम में 12/14~15 min
मॉड्यूल पाठ (2/2)

स्मार्ट पॉइंटर्स: बॉक्स और आरसी

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

रस्ट में, सामान्य संदर्भ (जैसे &) केवल डेटा उधार लेते हैं। दूसरी ओर, स्मार्ट पॉइंटर्स अक्सर उस डेटा के मालिक होते हैं जिस पर वे इशारा करते हैं। सामान्य उदाहरणों में String और Vec<T> शामिल हैं, लेकिन मानक पुस्तकालय अन्य विशिष्ट प्रदान करता है।


ढेर आवंटन के लिए बॉक्स<T>

सबसे सरल स्मार्ट पॉइंटर Box<T> है, जो डेटा को स्टैक के बजाय हीप पर संग्रहीत करता है। ढेर-आवंटित डेटा का केवल सूचक ही स्टैक पर रहता है।

इसका उपयोग मुख्य रूप से निम्नलिखित मामलों में किया जाता है:

  1. जब आपके पास एक प्रकार होता है जिसका आकार संकलन समय पर ज्ञात नहीं किया जा सकता है (जैसे एक पुनरावर्ती प्रकार), और आप उस प्रकार के मान का उपयोग उस संदर्भ में करना चाहते हैं जिसके लिए सटीक आकार की आवश्यकता होती है।
  2. जब आप बड़ी मात्रा में डेटा को कॉपी किए बिना उसका स्वामित्व स्थानांतरित करना चाहते हैं।

आधार उदाहरण:

Rust
fn main() {
    let b = Box::new(5); // allocates the value 5 on the heap
    println!("b = {}", *b); // dereferences with * to read the value
}

पुनरावर्ती प्रकार और विपक्ष सूचियाँ

पुनरावर्ती प्रकार एक ऐसा प्रकार है जिसमें इसकी परिभाषा के भाग के रूप में स्वयं का मान शामिल हो सकता है। संकलन के समय रस्ट को किसी प्रकार का सटीक आकार पता होना चाहिए। चूंकि पुनरावर्ती प्रकार की गहराई अनंत हो सकती है, कंपाइलर एक त्रुटि उत्पन्न करता है जब तक कि आप एक बॉक्स का उपयोग नहीं करते (जिसका एक निश्चित आकार होता है, क्योंकि यह एक सूचक है):

Rust
enum List {
    Cons(i32, Box<List>),
    Nil,
}

Rc<T>: संदर्भ गणना

ऐसे मामले हैं जहां एक ही मूल्य के कई मालिक हो सकते हैं। Rc<T> (संदर्भ गणना) स्मार्ट पॉइंटर किसी मान के संदर्भों की संख्या पर नज़र रखता है ताकि यह निर्धारित किया जा सके कि मान अभी भी उपयोग में है या नहीं। यदि गिनती शून्य हो जाती है, तो संसाधन सुरक्षित रूप से आवंटित कर दिया जाता है।

[!नोट] Rc<T> केवल एकल-थ्रेडेड परिदृश्यों के लिए उपयुक्त है। बहु-थ्रेडेड (समवर्ती) परिदृश्यों के लिए, आपको Arc<T> (परमाणु संदर्भ गणना) का उपयोग करना होगा।

Rust
use std::rc::Rc;

fn main() {
    let a = Rc::new(5);
    let b = Rc::clone(&a); // increments the reference count to 2
    println!("References: {}", Rc::strong_count(&a));
}

खुद कोशिश करना

अभ्यास 1: बॉक्स के साथ ढेर आवंटन

व्यायाम#rust.m6.l2.e1
प्रयास: 0लोड हो रहा है...

Box::new का उपयोग करके ढेर पर 42 का एक पूर्णांक मान आवंटित करें और इसे वैल नामक एक वेरिएबल पर असाइन करें। इसके बाद, बॉक्स में संग्रहीत मान को * ऑपरेटर के साथ स्पष्ट रूप से डीरेफ़रेंस करके प्रिंट करें।

संपादक लोड हो रहा है...
संकेत दिखाएँ

मान को ढेर में संग्रहीत करने के लिए `let val = Box::new(42);` का उपयोग करें और इसे `println!` के अंदर `*val` के साथ डीरेफ़रेंस करें।

3 प्रयासों के बाद समाधान उपलब्ध है

अभ्यास 2: पुनरावर्ती डेटा संरचना (विपक्ष सूची)

व्यायाम#rust.m6.l2.e2
प्रयास: 0लोड हो रहा है...

List नामक एक पुनरावर्ती एनम को परिभाषित करें जिसमें दो प्रकार हों: Cons जो एक टुपल (i32, Box<List>) को लपेटता है, और Nil जो सूची के अंत का प्रतिनिधित्व करता है। मुख्य फ़ंक्शन में, एक लिंक की गई सूची को इंस्टेंट करें जिसमें तत्व 1 और उसके बाद शून्य हो।

संपादक लोड हो रहा है...
संकेत दिखाएँ

एनम को `एनम लिस्ट { विपक्ष(i32, बॉक्स&lt;लिस्ट&gt;), शून्य }`के रूप में घोषित किया गया है।`List::Cons(1, Box::new(List::Nil))` के साथ सूची को त्वरित करें।

3 प्रयासों के बाद समाधान उपलब्ध है

अभ्यास 3: आरसी के साथ स्वामित्व साझा करना

व्यायाम#rust.m6.l2.e3
प्रयास: 0लोड हो रहा है...

एक वेरिएबल a में मान 100 वाला एक साझा पूर्णांक बनाने के लिए std::rc::Rc का उपयोग करें। Rc::clone का उपयोग करके संदर्भ को एक वेरिएबल b में क्लोन करें। अंत में, Rc::strong_count फ़ंक्शन का उपयोग करके सक्रिय संदर्भों की संख्या प्रिंट करें।

संपादक लोड हो रहा है...
संकेत दिखाएँ

`Rc::new(100)`के साथ मान बनाएं।`Rc::clone(&a)`के साथ क्लोन करें और`Rc::strong_count(&a)` के साथ मालिक की संख्या प्रदर्शित करें।

3 प्रयासों के बाद समाधान उपलब्ध है