দুটি বহুল ব্যবহৃত মেমরি বরাদ্দ কৌশল রয়েছে: স্বয়ংক্রিয় বরাদ্দ এবং গতিশীল বরাদ্দ। সাধারণত, প্রতিটিটির জন্য মেমরির সাথে সম্পর্কিত অঞ্চল রয়েছে: স্ট্যাক এবং হিপ।
গাদা
স্ট্যাকটি সর্বদা ক্রমান্বিত ফ্যাশনে মেমরির বরাদ্দ করে। এটি এমনটি করতে পারে কারণ এর জন্য আপনাকে বিপরীত ক্রমে মেমরিটি প্রকাশ করতে হবে (ফার্স্ট-ইন, লাস্ট-আউট: ফিলো)। এটি অনেক প্রোগ্রামিং ভাষায় স্থানীয় ভেরিয়েবলের জন্য মেমরি বরাদ্দ কৌশল। এটি খুব, খুব দ্রুত কারণ এটির জন্য ন্যূনতম বুককিপিং প্রয়োজন এবং বরাদ্দ করার পরবর্তী ঠিকানাটি অন্তর্ভুক্ত।
সি ++ এ এটিকে স্বয়ংক্রিয় স্টোরেজ বলা হয় কারণ স্টোরেজটি সুযোগের শেষে স্বয়ংক্রিয়ভাবে দাবি করা হয়। বর্তমান কোড ব্লকের (ব্যবহার করে সীমানা {}
) কার্যকর হওয়ার সাথে সাথে block ব্লকের সমস্ত ভেরিয়েবলের জন্য মেমরি স্বয়ংক্রিয়ভাবে সংগ্রহ করা হয়। এটি সেই মুহুর্তে যেখানে ধ্বংসকারীদের সংস্থানগুলি সংশোধন করার জন্য অনুরোধ করা হয়েছিল।
গাদা
গাদা আরও নমনীয় মেমরি বরাদ্দ মোডের জন্য অনুমতি দেয়। বুককিপিং আরও জটিল এবং বরাদ্দ ধীর। কোনও অন্তর্নিহিত প্রকাশের বিন্দু না থাকায় আপনাকে অবশ্যই মেমোরিটি ম্যানুয়ালি প্রকাশ করতে হবে delete
বা delete[]
( free
সি তে) ব্যবহার করতে হবে । যাইহোক, একটি নিখুঁত রিলিজ পয়েন্টের অনুপস্থিতি হ'ল নমনীয়তার মূল চাবিকাঠি।
গতিশীল বরাদ্দ ব্যবহারের কারণ
এমনকি যদি গাদাটি ব্যবহার করা ধীর হয় এবং সম্ভাব্যভাবে মেমরি ফাঁস বা মেমরি খণ্ডিত হতে থাকে তবে গতিশীল বরাদ্দের ক্ষেত্রে পুরোপুরি ভাল ব্যবহারের ঘটনা রয়েছে, কারণ এটি কম সীমাবদ্ধ।
গতিশীল বরাদ্দ ব্যবহারের দুটি মূল কারণ:
সংকলনের সময় আপনার কত স্মৃতি দরকার তা আপনি জানেন না। উদাহরণস্বরূপ, একটি টেক্সট ফাইলটি স্ট্রিংয়ে পড়ার সময়, আপনি সাধারণত ফাইলটির আকারের আকারটি জানেন না, সুতরাং আপনি প্রোগ্রামটি চালনা না করা পর্যন্ত কতটা মেমরি বরাদ্দ করতে হবে তা আপনি সিদ্ধান্ত নিতে পারবেন না।
আপনি মেমরি বরাদ্দ করতে চান যা বর্তমান ব্লকটি ছেড়ে যাওয়ার পরে অব্যাহত থাকবে। উদাহরণস্বরূপ, আপনি কোনও ফাংশন লিখতে চাইতে পারেন যা string readfile(string path)
কোনও ফাইলের বিষয়বস্তু ফেরত দেয়। এই ক্ষেত্রে, যদি স্ট্যাক পুরো ফাইল সামগ্রীটি ধারণ করতে পারে তবে আপনি কোনও ফাংশন থেকে ফিরে এসে বরাদ্দ হওয়া মেমরির ব্লক রাখতে পারবেন না।
গতিশীল বরাদ্দ কেন প্রায়শই অপ্রয়োজনীয়
সি ++ তে একটি ঝরঝরে কনস্ট্রাক্ট রয়েছে যার নাম ডেস্ট্রাক্টর । এই প্রক্রিয়াটি আপনাকে পরিবর্তকের জীবনকাল সহ সম্পদের আজীবন সারিবদ্ধ করে সংস্থানগুলি পরিচালনা করতে দেয়। এই কৌশলটিকে আরআইআইআই বলা হয় এবং এটি সি ++ এর বিশিষ্ট পয়েন্ট। এটি উত্সগুলিকে "মোড়ানো" করে ps std::string
একটি নিখুঁত উদাহরণ। এই স্নিপেট:
int main ( int argc, char* argv[] )
{
std::string program(argv[0]);
}
আসলে মেমরি একটি পরিবর্তনশীল পরিমাণ বরাদ্দ। std::string
বস্তুর বরাদ্দ মেমরির গাদা এবং তার নাশক এটা রিলিজ ব্যবহার করে। এই ক্ষেত্রে, আপনি হয়নি না প্রয়োজন যে কোনো সম্পদগুলি পরিচালনা করে এবং এখনও ডাইনামিক মেমরি বরাদ্দকরণের সুবিধাগুলো পেয়েছিলাম।
বিশেষত, এটি বোঝায় যে এই স্নিপেটে:
int main ( int argc, char* argv[] )
{
std::string * program = new std::string(argv[0]); // Bad!
delete program;
}
অপ্রয়োজনীয় গতিশীল মেমরি বরাদ্দ রয়েছে। প্রোগ্রামটির জন্য আরও টাইপিং (!) প্রয়োজন এবং মেমোরিটি হ্রাস করতে ভুলে যাওয়ার ঝুঁকিটি প্রবর্তন করে। এটি কোনও আপাত সুবিধার সাথে এটি করে।
আপনার যত দ্রুত সম্ভব স্বয়ংক্রিয় স্টোরেজ ব্যবহার করা উচিত
মূলত, শেষ অনুচ্ছেদে এটির যোগফল। যতবার সম্ভব স্বয়ংক্রিয় স্টোরেজ ব্যবহার করা আপনার প্রোগ্রামগুলিকে তোলে:
- টাইপ করতে দ্রুত;
- রান যখন দ্রুত;
- স্মৃতি / রিসোর্স লিকের প্রবণতা কম।
বোনাস পয়েন্ট
রেফারেন্স করা প্রশ্নে অতিরিক্ত উদ্বেগ রয়েছে। বিশেষত, নিম্নলিখিত শ্রেণি:
class Line {
public:
Line();
~Line();
std::string* mString;
};
Line::Line() {
mString = new std::string("foo_bar");
}
Line::~Line() {
delete mString;
}
নিম্নলিখিতগুলির তুলনায় আসলে ব্যবহার করা অনেক বেশি ঝুঁকিপূর্ণ:
class Line {
public:
Line();
std::string mString;
};
Line::Line() {
mString = "foo_bar";
// note: there is a cleaner way to write this.
}
কারণটি হ'ল std::string
একটি অনুলিপি নির্মাণকারীকে যথাযথভাবে সংজ্ঞা দেয়। নিম্নলিখিত প্রোগ্রাম বিবেচনা করুন:
int main ()
{
Line l1;
Line l2 = l1;
}
আসল সংস্করণ ব্যবহার করে, এই প্রোগ্রামটি সম্ভবত ক্রাশ হবে, কারণ এটি delete
একই স্ট্রিংয়ে দু'বার ব্যবহার করে। পরিবর্তিত সংস্করণ ব্যবহার করে, প্রতিটি Line
উদাহরণ নিজস্ব স্ট্রিং উদাহরণগুলির নিজস্ব হবে , প্রতিটি নিজস্ব স্মৃতিযুক্ত এবং উভয়ই প্রোগ্রামের শেষে প্রকাশিত হবে।
অন্যান্য নোট
উপরোক্ত সমস্ত কারণে সিআইএল -তে RAII এর বিস্তৃত ব্যবহার সেরা অভ্যাস হিসাবে বিবেচিত হয়। তবে, একটি অতিরিক্ত সুবিধা রয়েছে যা অবিলম্বে সুস্পষ্ট নয়। মূলত, এটি এর অংশগুলির যোগফলের চেয়ে ভাল। পুরো প্রক্রিয়াটি রচনা করে । এটি স্কেল করে।
আপনি যদি Line
ক্লাসটি বিল্ডিং ব্লক হিসাবে ব্যবহার করেন :
class Table
{
Line borders[4];
};
তারপর
int main ()
{
Table table;
}
চারটি std::string
দৃষ্টান্ত, চারটি Line
দৃষ্টান্ত, একটি Table
উদাহরণ এবং সমস্ত স্ট্রিংয়ের বিষয়বস্তু বরাদ্দ করে এবং সবকিছু স্বয়ংক্রিয়ভাবে মুক্ত হয় ।