Skip to content

মডিউল ২-০ঃ সূচনা

এই মডিউলে আমরা কি কি শিখবোঃ

  • ডায়নামিক এবং স্ট্যাটিক মেমরি সম্পর্কে জানবো

  • ডায়নামিক ভেরিয়েবল কিভাবে তৈরি হয় তা জানবো

  • ডায়নামিক এরে তৈরি করা দেখব

  • এরে কিভাবে ফাংশন থেকে রিটার্ন করতে হয় তা দেখব

  • ডায়নামিক মেমরি কিভাবে ডিলিট করতে হয় তা জানবো

মডিউল ২-১ঃ স্ট্যাটিক vs ডায়নামিক মেমরি

কম্পিউটারে দুই ধরনের মেমরি থাকে। স্ট্যাক মেমরি এবং হিপ মেমরি। স্ট্যাক মেমরিকে বলা হয় স্ট্যাটিক মেমরি এবং হিপ মেমরিকে বলা হয় ডায়নামিক মেমরি।

স্ট্যাটিক মেমরি হচ্ছে কম্পাইলটাইম মেমরি। ডায়নামিক মেমরি হচ্ছে রানটাইম মেমরি। স্ট্যাটিক মেমরিতে সীমিত মেমরি থাকে তাই স্ট্যাটিক মেমরিতে কোন এরে ডিক্লেয়ার করা হলে সেটিকে বলা হয় স্ট্যাটিক এরে এবং তার সাইজ চাইলে বাড়ানো যায় না। স্ট্যাটিক মেমরি যত সাইজের এরে ডিক্লেয়ার করা হয়েছে মেমরিতে ঠিক ততটুকু স্পেসই দখল করে। তাই পরবর্তীতে চাইলেও স্ট্যাটিক এরের সাইজ বাড়ানো যায় না।

ডায়নামিক মেমরিতে বেশি মেমরি থাকে তাই ডায়নামিক মেমরিতে কোন এরে ডিক্লেয়ার করা হলে সেটিকে বলা হয় ডায়নামিক এরে এবং তার সাইজ চাইলে বাড়ানো যায়।

স্ট্যাটিক এবং ডায়নামিক মেমরির আরেকটি পার্থক্য হচ্ছে স্ট্যাটিক মেমরি অটোমেটিক মেমরি ক্লিয়ার করে দেয় যা ডায়নামিক মেমরি করে না। স্ট্যাটিক মেমরিতে আমরা যদি কোন ফাংশনকে কল করে সেই ফাংশনের মধ্যে একটি স্ট্যাটিক এরে ডিক্লেয়ার করে সেটি মেইন ফাংশুনে রিটার্ন করে দেই, তাহলে দেখতে পাব মেইন ফাংশন থেকে সেই এরেকে এক্সেস করতে গেলে সব গারবেজ ভেলু পাওয়া যাচ্ছে। অর্থাৎ এরেটি ফাংশন থেকে রিটার্ন আসার পর স্ট্যাটিক মেমরি অটোমেটিক ফাংশনে থাকা এরে এবং সব ভেরিয়েবল ডিলিট করে দেয়। কিন্তু ডায়নামিক মেমরিতে আমরা যদি কোন ফাংশনকে কল করে সেই ফাংশনের মধ্যে একটি ডায়নামিক এরে ডিক্লেয়ার করে সেটি মেইন ফাংশুনে রিটার্ন করে দেই, তাহলে দেখতে পাব মেইন ফাংশন থেকে সেই এরের সব ভেলু পাওয়া যাচ্ছে।অর্থাৎ এরেটি ফাংশন থেকে রিটার্ন আসার পর ডায়নামিক মেমরি এরেটিকে ডিলিট করে দেয় নি। ডায়নামিক মেমরি ইউজার এর ইন্সট্রাকশন ছাড়া কোন মেমরি ডিলিট করে না।

মডিউল ২-২ঃ ক্রিয়েট ডায়নামিক মেমরি

এবার আমরা দেখব কিভাবে ডায়নামিক মেমরিতে ভেরিয়েবল ক্রিয়েট করতে হয়

স্ট্যাটিক মেমরিতে ভেরিয়বেল ডিক্লেয়ার করাঃ

cpp
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int x = 10;          // একটি ইন্টিজার ভেরিয়েবল ডিক্লেয়ার করে তাতে ১০ রেখে দেওয়া হচ্ছে।
    cout << x << endl;   // ভেরিয়েবলটি প্রিন্ট করা হচ্ছে।
}

ডায়নামিক মেমরিতে ভেরিয়েবল ডিক্লেয়ার করাঃ

ডায়নামিক মেমরিতে ভেরিয়েবল ডিক্লেয়ার করার সিন্টেক্সঃ

cpp
data_type * pointer_name  = new data_type

এই সিন্টেক্স ফলো করলে ডায়নামিক মেমরিতে একটি ভেরিয়েবল ক্রিয়েট হয় এবং তার এড্রেস স্টোর থাকে পয়েন্টার এর মধ্যে। এখানে লক্ষণীয় ব্যাপার হচ্ছে পয়েন্টারটি কিন্তু স্টোর থাকে স্ট্যাটিক মেমরিতে।

cpp
#include<bits/stdc++.h>

using namespace std;

int main()
{
 int *x = new int; // ডায়নামিক মেমরিতে একটি ইন্টিজার ভেরিয়েবল ডিক্লেয়ার হলো এবং তার এড্রেস স্টোর করা হচ্ছে p নামক পয়েন্টারে।
 *x = 10; // পয়েন্টারকে ডিরেফারেন্স করে ডায়নামিক মেমরিতে স্টোর থাকা ভেরিয়েবলের মধ্যে ১০ রেখে দেওয়া হচ্ছে।
 cout << *x << endl; // পয়েন্টারকে ডিরেফারেন্স করে ভেরিয়েবলটি প্রিন্ট করা হচ্ছে।
}

এভাবে আমরা ডায়নামিক মেমরিতে ভেরিয়েবল ক্রিয়েট করতে পারি।

মডিউল ২-৩, ২-৬ঃ ক্রিয়েট ডায়নামিক এরে এবং রিটার্ন এরে ফ্রম ফাংশন

এবার আমরা দেখব কিভাবে ডায়নামিক এরে ক্রিয়েট করতে হয় এবং ফাংশন থেকে রিটার্ন করতে হয়।

ডায়নামিক ভেরিয়েবল ডিক্লেয়ার এর মতো করেই আমরা ডায়নামিক এরে ডিক্লেয়ার করতে পারি। ডায়নামিক এরে আমরা নরমাল এরের মতোই ইনপুট নিতে পারব এবং আউটপুট শো করতে পারব।

cpp
#include<bits/stdc++.h>

using namespace std;

int main()
{
 int n;
 cin >> n; // এরে সাইজ ইনপুট নিচ্ছি।
 int *a = new int[n]; // সেই সাইজের ডায়নামিক এরে ডিক্লেয়ার করছি যা হিপ মেমরিতে স্টোর থাকবে।
 for (int i = 0; i < n; i++)
 {
 cin >> a[i]; // নরমাল পদ্ধতিতে এরে ইনপুট নিচ্ছি।
 }
 for (int i = 0; i < n; i++)
 {
 cout << a[i] << endl; // নরমাল পদ্ধতিতে আউটপুট দেখাচ্ছি।
 }
 return 0;
}

আমরা যদি ফাংশনের মধ্যে একটি স্ট্যাটিক এরে ডিক্লেয়ার করে তা মেইন ফাংশনে রিটার্ন করতে চাইঃ

cpp
#include<bits/stdc++.h>
using namespace std;
int* fun()
{
 int a[5]; // ৫ সাইজের স্ট্যাটিক এরে ডিক্লেয়ার করা হয়েছে।
 for(int i=0;i<5;i++)
 {
 cin >> a[i]; // ইউজার থেকে এরে এলিমেন্ট ইনপুট নেওয়া হচ্ছে।
 }
 return a; // স্ট্যাটিক এরে রিটার্ন করে দেওয়া হচ্ছে।
}

int main()
{
 int *p = fun(); // স্ট্যাটিক এরে রিসিভ করা হচ্ছে পয়েন্টার দিয়ে।
 for(int i=0;i<5;i++)
 {
 cout << p[i] << " "; // সেই পয়েন্টার দিয়ে এরে এলিমেন্ট প্রিন্ট করার চেষ্টা করা হচ্ছে।
 }
}

তাহলে আমরা দেখব কোড রান করলে সেগমেন্টেশন ফল্ট আসছে। যখনি ফাংশন থেকে রিটার্ন হয়ে আমরা মেইন ফাংশনে আসছি তখন ফাংশনে থাকা সব ভেরিয়েবল এবং এরে স্ট্যাক মেমরি অটো ডিলিট করে দিয়েছে। তাই আমরা যখন মেইন ফাংশন থেকে সেই এরে প্রিন্ট করার ট্রাই করছি তখন সেগমেন্টেশন ফল্ট আসছে কারন আমরা এমন মেমরি এক্সেস করার চেষ্টা করছি যা মেমরিতে নাই, ইতিমধ্যে ডিলিট হয়ে গিয়েছে। তাই আমাদের যদি ফাংশনের মধ্যে ডিক্লেয়ার করা এরে রিটার্ন করার প্রয়োজন হয় তাহলে আমরা ডায়নামিক এরে ডিক্লেয়ার করব।

cpp
#include<bits/stdc++.h>
using namespace std;
int* fun()
{
 int * a = new int [5]; // ৫ সাইজের ডায়নামিক এরে ডিক্লেয়ার করা হয়েছে।
 for(int i=0;i<5;i++)
 {
 cin >> a[i]; // ইউজার থেকে এরে এলিমেন্ট ইনপুট নেওয়া হচ্ছে।
 }
 return a; // ডায়নামিক এরে রিটার্ন করে দেওয়া হচ্ছে।
}

int main()
{
 int *p = fun(); // ডায়নামিক এরে রিসিভ করা হচ্ছে পয়েন্টার দিয়ে।
 for(int i=0;i<5;i++)
 {
 cout << p[i] << " "; // সেই পয়েন্টার দিয়ে এরে এলিমেন্ট প্রিন্ট করা হচ্ছে।
 }
}

এই কোডটি রান করলে আমরা দেখব ঠিকঠাক আউটপুট আসছে। এখানে আমরা এরে ডিক্লেয়ার করছি হিপ মেমরিতে তাই ফাংশন থেকে রিটার্ন হওয়ার পর হিপ মেমরি অটোমেটিক এরে ডিলিট করে দেয় নি।

মডিউল ২-৪, ২-৫ঃ ইনক্রিজ সাইজ অফ এরে এবং ডিলিট ডায়নামিক মেমরি

এবার আমরা দেখব কিভাবে একটি এরে ডিক্লেয়ার করার পর তার সাইজ বাড়াতে পারি এবং ডায়নামিক মেমরি কিভাবে ডিলিট করতে পারি।

স্ট্যাটিক এরে একবার ডিক্লেয়ার করার পর সেই এরের সাইজ বাড়ানোর কোন উপায় থাকে না। নতুন এরে ডিক্লেয়ার করতে হয়। কিন্তু এখানে আগের এরে থেকে যায়, যেটি ডিলিট করা যায় না, যার ফলে অনেক মেমরি অপচয় হয়।

ডায়নামিক মেমরি ডিলিট করা যায় তাই ডায়নামিক মেমরিতে এই সমস্যা হয় না।

cpp
#include<bits/stdc++.h>

using namespace std;

int main()
{
 int *a = new int[5]; // ৫ সাইজের ডায়নামিক এরে ডিক্লেয়ার করা হয়েছে।
 for(int i=0;i<5;i++)
 {
 cin >> a[i]; // এরে এলিমেন্ট ইনপুট নেওয়া হয়েছে।
 }
 for(int i=0;i<5;i++)
 {
 cout << a[i] << " "; // এরে এলিমেন্ট প্রিন্ট করা হয়েছে।
 }
 cout << endl;
 delete[] a; // ডায়নামিক এরে ডিলিট করে দেওয়া হয়েছে।
 for(int i=0;i<5;i++)
 {
 cout << a[i] << " "; // ডিলিট করার পর এরে এলিমেন্ট প্রিন্ট করা হয়েছে।
 }
}

কোডটি রান করলে দেখতে পাব এরে ইনপুট নেওয়ার পর প্রিন্ট হচ্ছে। পরবর্তীতে এরে ডিলিট করার পর প্রিন্ট হচ্ছে গারবেজ ভেলু। তারমানে এরে ডিলিট হয়েছে।

এবার আমরা দেখব কিভাবে ডায়নামিক এরের সাইজ বাড়ানো যায়। ধরি আমাদের কাছে একটি A এরে আছে ৩ সাইজের। আমাদের A এরেটি দরকার ৫ সাইজের। এখন আমরা যেটি করব তা হলো আরেকটি B এরে নিব। B এরেতে A এরের সবগুলো এলিমেন্ট কপি করে রেখে দিব। তারপর A এরে ডিলিট করে দিয়ে নতুন করে A এরে ডিক্লেয়ার করব ৫ সাইজের। এরপর A এরেতে B এরের সবগুলো এলিমেন্ট কপি করে রেখে দিব। তারপর B এরে ডিলিট করে দিব। তাহলে এখন আমাদের কাছে একটিই এরে আছে A এরে যার সাইজ হচ্ছে ৫। এই প্রসেস স্ট্যাটিক এরের ক্ষেত্রে প্রযোজ্য না কারন স্ট্যাটিক এরে ডিলিট করা যায় না।

cpp
#include<bits/stdc++.h>

using namespace std;

int main()
{
 int *a = new int[3]; // a এরে আছে ৩ সাইজের।
 int *b = new int[3]; // কপি করে রাখার জন্য আরেকটি b এরে নেওয়া হলো সেইম সাইজের।
 for (int i = 0; i < 3; i++)
 {
 cin >> a[i]; // ইনপুট নিয়ে a এরেতে রাখা হচ্ছে।
 b[i] = a[i]; // কপি করে b এরেতে রাখা হচ্ছে।
 }

 delete[] a; // a ডিলিট করে দেওয়া হলো।

 a = new int[5]; // নতুন করে a এরে ডিক্লেয়ার করা হলো ৫ সাইজের।
 for (int i = 0; i < 3; i++)
 {
 a[i] = b[i]; // b এরে থেকে কপি করে a এরেতে রাখা হচ্ছে।
 }
 delete[] b; // এবার b ডিলিট করে দেওয়া হলো।
 a[3] = 40; // এখন আমাদের কাছে একটিই এরে আছে a এরে, যার সাইজ হচ্ছে ৫। এবং এর প্রথম ৩ ইন্ডেক্সে পূর্বের ৩টি ভেলু স্টোর আছে। এবার শেষের দুটি ইন্ডেক্সে ভেলু রাখা হচ্ছে।
 a[4] = 50;
 for (int i = 0; i < 5; i++)
 cout << a[i] << " "; // a এরে প্রিন্ট করা হচ্ছে।
 return 0;
}

এভাবে আমরা একটি ডায়নামিক এরের সাইজ প্রয়োজনমতো বাড়িয়ে নিতে পারি।

Released under the MIT License.