الرجوع للقائمة الرئيسية (Back to Home)

Lecture 5: Dynamic Memory Allocation

المحاضرة الخامسة: حجز الذاكرة الديناميكي (Dynamic Memory)

الشرح التفصيلي لجميع شرائح المحاضرة (Slide-by-Slide) مدعوم بشرح الأكواد سطراً بسطر (Line-by-Line Code Explanation)

Slide 3: الذاكرة الثابتة مقابل الديناميكية (Static vs Dynamic Memory)

Slide 3

في لغة الـ C++، الذاكرة (Memory) اللي البرنامج بيستخدمها بتتقسم لجزئين أساسيين:

  • الـ Stack (الذاكرة الثابتة/المحلية): دي الذاكرة اللي الكومبايلر بيديرها بنفسه. المتغيرات العادية (زي int x) بتتحط هنا. الميزة إنها سريعة جداً وبتتمسح لوحدها، بس العيب إن حجمها لازم يكون معروف وقت الـ Compile Time (قبل ما البرنامج يشتغل) وصعب تغيره.
  • الـ Heap (الذاكرة الديناميكية): ده بحر من الميموري الفاضية. بتستخدمه لما تكون مش عارف إنت محتاج ميموري قد إيه إلا وقت ما البرنامج يشتغل (Run-Time)، مثلاً: اليوزر هو اللي بيدخل عدد الطلبة. هنا أنت كمبرمج اللي بتدير الذاكرة دي بإيدك.

Slide 4: المؤشرات (Pointers Refresher)

Slide 4

عشان نقدر نتعامل مع الـ Heap (الذاكرة الديناميكية)، لازم نستخدم الـ Pointers (المؤشرات).

الـ Pointer هو متغير عادي جداً، بس بدل ما يشيل رقم أو حرف، بيشيل عنوان (Memory Address) لمتغير تاني.

  • علامة الـ * بتستخدم وإحنا بنعرف البوينتر: int *ptr;
  • علامة الـ & بتستخدم عشان نجيب عنوان متغير عادي: ptr = &x;
  • علامة الـ * بتستخدم تاني عشان نجيب القيمة اللي البوينتر بيشاور عليها (Dereferencing): cout << *ptr;

Slide 5: الكلمة المحجوزة new (The 'new' Operator)

Slide 5

إزاي نحجز مكان في الـ Heap؟ بنستخدم الكلمة السحرية new.

كلمة new بتعمل حاجتين:

  1. بتروح للـ Heap تدور على مساحة فاضية تكفي النوع اللي طلبته (مثلاً 4 بايت لو int).
  2. بترجعلك العنوان (Address) بتاع المساحة دي. عشان كده دايماً وأبداً لازم نستقبل نتيجة الـ new جوه Pointer.
int *ptr; // 1. Create a pointer ptr = new int; // 2. Allocate dynamic memory and store the address in ptr *ptr = 55; // 3. Store a value in that memory

Slide 6: الكلمة المحجوزة delete (The 'delete' Operator)

Slide 6

بما إنك بقيت المدير، الكومبايلر مش هيمسح الحاجة اللي إنت حجزتها بـ new حتى لو البرنامج خلص! لازم إنت اللي تنضف وراك.

عشان كده بنستخدم الكلمة العكسية delete. دي بتروح تفضي وتمسح المساحة اللي البوينتر كان بيشاور عليها وترجعها للسيستم.

delete ptr; // Frees the dynamically allocated memory ptr = NULL; // Best Practice: Set pointer to NULL after deletion to avoid dangling pointers

Slide 7: المصفوفات الديناميكية (Dynamic Arrays)

Slide 7

أكبر فايدة للـ Dynamic Memory هي إننا نعمل מصفوفة (Array) حجمها مش ثابت، حجمها بيتحدد وإحنا مشغلين البرنامج.

عشان نحجز Array ديناميكية، بنكتب الأقواس المربعة [] بعد النوع، وجواها المتغير اللي بيمثل الحجم.

int size; cout << "Enter number of students: "; cin >> size; // Allocation based on user input! (Impossible in Static Stack memory) int *arr = new int[size]; for(int i = 0; i < size; i++) { arr[i] = i * 10; // Used just like a normal array }

Slide 8: مسح المصفوفات الديناميكية (Deleting Dynamic Arrays)

Slide 8

غلطة شائعة جداً (وبتوقع ناس كتير في الـ Memory Leaks): لما تيجي تمسح مصفوفة محجوزة بـ new []، لازم تستخدم delete [] (مع الأقواس المربعة الفاضية).

لو استخدمت delete ptr; العادية، الكومبايلر هيمسح أول عنصر بس في الـ Array ويسيب الباقي محجوز للأبد (Memory Leak)!

// Correct way to delete a dynamic array delete[] arr; arr = NULL;

Quiz 1: Pointers & New/Delete

1. Which of the following is the correct syntax to dynamically allocate a single integer and initialize it with the value 10?

2. What happens if you forget to use the `delete` operator on memory allocated with `new`?

Slide 12: حجز الكائنات ديناميكياً (Dynamic Objects)

Slide 12

زي ما حجزنا int، نقدر نحجز Object كامل بنفس الطريقة بالظبط!

لما بنستخدم new ClassName، بيحصل حاجتين في نفس اللحظة:

  1. مكان بيتحجز في الـ Heap يكفي الداتا بتاعة الـ Object ده.
  2. الـ Constructor بيشتغل أوتوماتيك عشان يهيئ المكان ده! (دي ميزة عظيمة لـ new).
Student *s_ptr; s_ptr = new Student; // Calls Default Constructor // Or if you have a Parameterized Constructor: Student *s_ptr2 = new Student(101, 3.5);

Slide 16: معامل السهم (The Arrow Operator ->)

Slide 16

لو معاك Object عادي بتستخدم الدوت (.) عشان توصل لدواله (مثلاً s1.display()).

طيب لو معاك Pointer بيشاور على Object؟ إزاي توصل للدوال؟

عندنا طريقتين:

  1. الطريقة العقيمة: تفك البوينتر الأول بالنجمة *، وتحطهم في أقواس، وبعدين تستخدم الدوت: (*s_ptr).display(); (محدش بيستخدمها لأنها بتلخبط).
  2. الطريقة البروفيشنال (Arrow Operator): بنستخدم السهم -> (عبارة عن علامة ناقص وراها أكبر من). السهم ده بيعمل فك للبوينتر وبيوصل للدالة في خطوة واحدة!
Student *s = new Student(1, "Ali"); s->display(); // Equivalent to (*s).display()

Slide 19: مصفوفة كائنات ديناميكية (Dynamic Array of Objects)

Slide 19

تخيل عايز تعمل سيستم لجامعة، وعدد الطلبة مجهول. هتحتاج مصفوفة كائنات ديناميكية.

الـ Syntax هنا بيجمع بين اللي اتعلمناه في الـ Arrays وفي الـ Objects:

int num_students; cin >> num_students; // Create dynamic array of Objects (Calls Default Constructor N times) Student *arr = new Student[num_students]; for(int i = 0; i < num_students; i++) { // Normal dot operator here because arr[i] IS the object itself, not a pointer arr[i].set_data(i, 0.0); arr[i].display(); } // Clean up! (Calls Destructor N times) delete[] arr;

Slide 20: مؤشر This السحري (The 'this' Pointer)

Slide 20

موضوع في قمة الأهمية وبيجي في الانترفيوهات: إيه هو الـ this pointer؟

جوه أي دالة في الـ Class (ما عدا الـ Static functions)، فيه بوينتر مخفي الكومبايلر بيكريته لوحده اسمه this.

البوينتر ده بيشاور على الكائن الحالي (Current Object) اللي نادى على الدالة. كأن الكائن بيبص في المراية وبيقول "أنا".

Slide 21: استخدامات مؤشر This (When to use 'this')

Slide 21

أشهر وأهم استخدام للـ this هو حل تعارض الأسماء (Resolving Name Shadowing).

تخيل إنك بتعمل Parameterized Constructor، واسم المدخلات (Parameters) هو نفس اسم المتغيرات بتاعت الكلاس (Data Members). الكومبايلر هيعرف منين إنت تقصد مين؟

class Box { private: int length; // Class member public: // Parameter has the EXACT SAME NAME 'length' Box(int length) { // length = length; // WRONG! Compiler gets confused. // RIGHT! this->length means the class member. // length (without this) means the parameter. this->length = length; } };

Final Quiz: Arrow Operator & 'this' Pointer

1. If `ptr` is a pointer to an object of class `Car` which has a method `startEngine()`, which of the following is the correct and most standard way to call it?

2. Inside a class method, what exactly does the `this` pointer represent?

الملخص الشامل لأهم التريكات (Summary & Pro Tips)

سؤال مقالي متوقع للامتحان (Essay Question)

Question: Explain Dynamic Memory Allocation in C++ using `new` and `delete`. Discuss Stack vs Heap, dynamic objects/arrays, the Arrow Operator, and the `this` pointer.

🖥️ What is the output of the following code?

Q1:

int main() { int *p = new int(7); cout << *p << endl; *p = 15; cout << *p << endl; delete p; }

Q2:

class Box { public: int size; Box(int s) { size = s; } }; int main() { Box *ptr = new Box(25); cout << ptr->size << endl; delete ptr; }

✍️ Write a line of code for the following statements

Q1: Dynamically allocate a single integer and initialize it to 42.

Q2: Dynamically allocate an array of 10 integers.

Q3: Delete the dynamic array from Q2 correctly.

Q4: Create a dynamic object of class Student using a parameterized constructor with id=5.

🔍 Based on the following code, answer all the following questions

class Rect { private: int length; public: Rect(int length) { this->length = length; } int getLength() { return length; } }; int main() { Rect *r = new Rect(8); cout << r->getLength() << endl; delete r; }

a) What is the output?

b) Why is this->length used instead of just length = length?

c) What happens if we remove the line delete r;?