মূল কন্টেন্টে যান
মডিউল 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লোড হচ্ছে...

দুটি ভেরিয়েন্ট সম্বলিত তালিকা নামের একটি পুনরাবৃত্ত enum সংজ্ঞায়িত করুন: Cons যা একটি tuple (i32, Box<List>) এবং Nil যা তালিকার শেষ প্রতিনিধিত্ব করে। প্রধান ফাংশনে, একটি লিঙ্কযুক্ত তালিকাকে ইনস্ট্যান্টিয়েট করুন যার মধ্যে 1 উপাদানটি Nil দ্বারা অনুসরণ করা হয়েছে।

সম্পাদক লোড হচ্ছে...
ইঙ্গিত দেখান

enum ঘোষণা করা হয় `enum List { Cons(i32, Box<List>), Nil }` হিসেবে। 'তালিকা::কনস(1, বক্স::নতুন (তালিকা::শূন্য))' দিয়ে তালিকাটি ইনস্ট্যান্টিয়েট করুন।

সমাধান 3 প্রচেষ্টার পরে উপলব্ধ

অনুশীলন 3: Rc এর সাথে মালিকানা ভাগ করা

ব্যায়াম#rust.m6.l2.e3
প্রচেষ্টা: 0লোড হচ্ছে...

একটি ভেরিয়েবল এ 100 মান ধারণকারী একটি ভাগ করা পূর্ণসংখ্যা তৈরি করতে std::rc::Rc ব্যবহার করুন। Rc::clone ব্যবহার করে একটি পরিবর্তনশীল b-এ রেফারেন্স ক্লোন করুন। অবশেষে, Rc::strong_count ফাংশন ব্যবহার করে সক্রিয় রেফারেন্সের গণনা প্রিন্ট করুন।

সম্পাদক লোড হচ্ছে...
ইঙ্গিত দেখান

`Rc::new(100)`দিয়ে মান তৈরি করুন।`Rc::clone(&a)`দিয়ে ক্লোন করুন এবং`Rc::strong_count(&a)` দিয়ে মালিকের সংখ্যা প্রদর্শন করুন।

সমাধান 3 প্রচেষ্টার পরে উপলব্ধ