এটি লক্ষ করা উচিত যে এটি সি ++ এর ক্ষেত্রে একটি সাধারণ ভুল ধারণা যে "আপনাকে ম্যানুয়াল মেমরি পরিচালনা করতে হবে"। আসলে, আপনি সাধারণত আপনার কোডটিতে কোনও মেমরি পরিচালনা করেন না।
স্থির আকারের অবজেক্টস (স্কোপ আজীবন সহ)
যখন আপনার কোনও সামগ্রীর প্রয়োজন হয় তখন বেশিরভাগ ক্ষেত্রে, আপনার প্রোগ্রামে এই অবজেক্টটির একটি নির্দিষ্ট জীবনকাল থাকবে এবং এটি স্ট্যাকের উপরে তৈরি হবে। এটি সমস্ত অন্তর্নির্মিত আদিম ডেটা ধরণের জন্য কাজ করে, তবে ক্লাস এবং স্ট্রাক্টগুলির উদাহরণগুলির জন্যও:
class MyObject {
public: int x;
};
int objTest()
{
MyObject obj;
obj.x = 5;
return obj.x;
}
ফাংশন শেষ হয়ে গেলে স্ট্যাক অবজেক্টগুলি স্বয়ংক্রিয়ভাবে সরানো হয়। জাভাতে সর্বদা অবধি বস্তুগুলি তৈরি করা হয় এবং তাই আবর্জনা সংগ্রহের মতো কোনও প্রক্রিয়া দ্বারা মুছে ফেলতে হয়। এটি স্ট্যাক অবজেক্টগুলির জন্য একটি নন-ইস্যু।
গতিশীল ডেটা পরিচালনা করে এমন অবজেক্টস (স্কোপ লাইফটাইম সহ)
স্ট্যাকের স্থান ব্যবহার করা একটি নির্দিষ্ট আকারের অবজেক্টের জন্য কাজ করে। যখন আপনার অ্যারে হিসাবে চলক পরিমাণের প্রয়োজন হয়, তখন অন্য পদ্ধতির ব্যবহার করা হয়: তালিকাটি একটি স্থির আকারের বস্তুতে আবদ্ধ থাকে যা আপনার জন্য গতিশীল মেমরি পরিচালনা করে। এটি কাজ করে কারণ অবজেক্টগুলির একটি বিশেষ ক্লিনআপ ফাংশন থাকতে পারে ruct যখন বস্তুটি সুযোগের বাইরে চলে যায় এবং নির্ধারকের বিপরীতে থাকে তখন এটি কল করার নিশ্চয়তা দেওয়া হয়:
class MyList {
public:
// a fixed-size pointer to the actual memory.
int* listOfInts;
// constructor: get memory
MyList(size_t numElements) { listOfInts = new int[numElements]; }
// destructor: free memory
~MyList() { delete[] listOfInts; }
};
int listTest()
{
MyList list(1024);
list.listOfInts[200] = 5;
return list.listOfInts[200];
// When MyList goes off stack here, its destructor is called and frees the memory.
}
যে কোডটিতে মেমরিটি ব্যবহৃত হয় সেখানে কোনও মেমরি পরিচালনা নেই। আমাদের কেবল এটি নিশ্চিত করতে হবে যে আমরা যে জিনিসটি লিখেছি তার উপযুক্ত ডেস্ট্রাক্টর রয়েছে। আমরা কীভাবে এই ক্ষেত্রটি ছেড়ে দিই না কেন listTest
, এটি কোনও ব্যতিক্রমের মাধ্যমে বা কেবল এখান থেকে ফিরে আসার পরে, ধ্বংসকারীকে ~MyList()
ডাকা হবে এবং আমাদের কোনও স্মৃতি পরিচালনা করার দরকার নেই।
(আমি মনে করি যে বাইনারি নট অপারেটরটি ~
ব্যবহার করে, বিনষ্টকারীকে ইঙ্গিত করার জন্য এটি একটি মজার ডিজাইনের সিদ্ধান্ত on
মূলত সমস্ত সি ++ অবজেক্ট যাদের ডায়নামিক মেমোরি প্রয়োজন তারা এই এনক্যাপসুলেশনটি ব্যবহার করে। একে আরআইআই ("রিসোর্স অধিগ্রহণ ইনিশিয়ালাইজেশন") বলা হয়ে থাকে, যা বস্তুগুলি তাদের নিজস্ব বিষয়বস্তুগুলি সম্পর্কে যত্নশীল এমন সহজ ধারণাটি প্রকাশ করার পক্ষে এক বিচিত্র উপায়; তারা যা অর্জন করবে তা তাদের পরিষ্কার করা।
বহুমুখী বস্তু এবং আধিপত্যের বাইরে
এখন, এই দুটি ক্ষেত্রেই ছিল স্মৃতির জন্য যা একটি স্পষ্টভাবে সংজ্ঞায়িত আজীবন রয়েছে: আজীবন সুযোগটি একই। আমরা যদি সুযোগটি ছাড়ার সময় কোনও বস্তুর মেয়াদ শেষ হতে না চাই, তৃতীয় প্রক্রিয়া রয়েছে যা আমাদের জন্য স্মৃতি পরিচালনা করতে পারে: একটি স্মার্ট পয়েন্টার। স্মার্ট পয়েন্টারগুলি তখনও ব্যবহৃত হয় যখন আপনি যখন অবজেক্টগুলির উদাহরণ রানটাইমের সময় পরিবর্তিত হয়ে থাকেন তবে এর মধ্যে একটি সাধারণ ইন্টারফেস বা বেস শ্রেণি থাকে:
class MyDerivedObject : public MyObject {
public: int y;
};
std::unique_ptr<MyObject> createObject()
{
// actually creates an object of a derived class,
// but the user doesn't need to know this.
return std::make_unique<MyDerivedObject>();
}
int dynamicObjTest()
{
std::unique_ptr<MyObject> obj = createObject();
obj->x = 5;
return obj->x;
// At scope end, the unique_ptr automatically removes the object it contains,
// calling its destructor if it has one.
}
std::shared_ptr
বেশ কয়েকটি ক্লায়েন্টের মধ্যে ভাগ করে নেওয়ার জন্য অন্য ধরণের স্মার্ট পয়েন্টার রয়েছে । শেষ ক্লায়েন্ট সুযোগের বাইরে চলে গেলে তারা কেবল তাদের অন্তর্ভুক্ত বস্তুটি মুছে দেয়, সুতরাং তাদের এমন পরিস্থিতিতে ব্যবহার করা যেতে পারে যেখানে কত ক্লায়েন্ট থাকবে এবং তারা কতক্ষণ অবজেক্টটি ব্যবহার করবে এটি সম্পূর্ণ অজানা।
সংক্ষেপে, আমরা দেখতে পাই যে আপনি সত্যিই কোনও ম্যানুয়াল মেমরি পরিচালনা করেন না do সমস্ত কিছু এনক্যাপসুলেটেড হয় এবং তারপরে সম্পূর্ণ স্বয়ংক্রিয়, স্কোপ-ভিত্তিক মেমরি পরিচালনার মাধ্যমে যত্ন নেওয়া হয়। যে ক্ষেত্রে এটি পর্যাপ্ত নয়, সেখানে স্মার্ট পয়েন্টার ব্যবহার করা হয় যা কাঁচা মেমরিকে আবৃত করে।
সি ++ কোডের যে কোনও জায়গায় রিসোর্স মালিক হিসাবে কাঁচা পয়েন্টার ব্যবহার করা, নির্মাতাদের বাইরে কাঁচা বরাদ্দ এবং delete
ডেস্ট্রাক্টরের বাইরে কাঁচা কলগুলি ব্যবহার করা চূড়ান্ত খারাপ অনুশীলন হিসাবে বিবেচিত হয় , কারণ ব্যতিক্রমগুলি দেখা দেওয়ার সময় তারা পরিচালনা করা প্রায় অসম্ভব এবং সাধারণত নিরাপদে ব্যবহার করা শক্ত।
সেরা: এটি সমস্ত ধরণের সংস্থার জন্য কাজ করে
আরআইআইআইর সবচেয়ে বড় সুবিধা হ'ল এটি কেবল স্মৃতিতে সীমাবদ্ধ নয়। এটি ফাইল এবং সকেট (উদ্বোধন / সমাপনীকরণ) এবং মাইটেক্সেস (লকিং / আনলকিং) এর মতো সিঙ্ক্রোনাইজেশন প্রক্রিয়াগুলির মতো সংস্থানগুলি পরিচালনা করার জন্য খুব প্রাকৃতিক উপায় সরবরাহ করে। মূলত, যে সমস্ত সংস্থান অর্জন করা যেতে পারে এবং ছেড়ে দিতে হবে সেগুলি অবশ্যই সি ++-তে ঠিক একই পদ্ধতিতে পরিচালিত হয় এবং এই পরিচালনার কোনওটিই ব্যবহারকারীর হাতে থাকে না। এটি সমস্ত ক্লাসে আবদ্ধ হয় যা কনস্ট্রাক্টর অর্জন করে এবং ডেস্ট্রাক্টরে প্রকাশ করে।
উদাহরণস্বরূপ, একটি মিউটেক্স লক করা একটি ফাংশন সাধারণত সি ++ এ লেখা হয়:
void criticalSection() {
std::scoped_lock lock(myMutex); // scoped_lock locks the mutex
doSynchronizedStuff();
} // myMutex is released here automatically
অন্য ভাষাগুলি এটিকে আরও জটিল করে তোলে, হয় আপনাকে ম্যানুয়ালি এই কাজটি করার প্রয়োজন হয় (উদাহরণস্বরূপ একটি finally
অনুচ্ছেদে) অথবা তারা বিশেষায়িত প্রক্রিয়া উদ্ভাবন করে যা এই সমস্যাটি সমাধান করে, তবে বিশেষভাবে মার্জিত উপায়ে নয় (সাধারণত তাদের জীবনে পরে যখন যথেষ্ট লোক থাকে) সংকট থেকে ভোগা)। এই জাতীয় প্রক্রিয়াগুলি জাভাতে রিসোর্সগুলি চেষ্টা করে এবং সি # তে ব্যবহারের বিবৃতি, উভয়ই সি ++ এর আরআইআইয়ের অনুমান।
সুতরাং, সংক্ষেপে বলতে গেলে, এগুলি সমস্তই সি ++ এ আরআইআইয়ের একটি অতি পৃষ্ঠপোষক বিবরণ ছিল, তবে আমি আশা করি এটি পাঠকদের বুঝতে সহায়তা করে যে মেমরি এবং এমনকি সি ++ এ রিসোর্স পরিচালনা সাধারণত "ম্যানুয়াল" নয়, তবে বেশিরভাগই স্বয়ংক্রিয়ভাবে স্বয়ংক্রিয়।