🔥 أحدث الأخبار

موقع يهتم بكل ماهو جديد في عالم التكنولوجيا والرياضة

كورس C++ المتوسط – الحلقة الرابعة: الذاكرة الديناميكية (Dynamic Memory) والمؤشرات المتقدمة


 

كورس C++ المتوسط – الحلقة الرابعة: الذاكرة الديناميكية (Dynamic Memory) والمؤشرات المتقدمة

#برمجة

مقدمة

مرحباً بك في الحلقة الرابعة من المستوى المتوسط في C++.

في الحلقة السابقة تعلمنا:

  • Vector
  • STL
  • sort
  • max_element
  • min_element
  • Pair

واليوم سندخل إلى أحد أهم المواضيع في C++ والذي يجعلها لغة قوية جداً:

الذاكرة الديناميكية (Dynamic Memory)

وفهم هذا الدرس سيساعدك لاحقاً على تعلم:

  • Linked List
  • Stack
  • Queue
  • Trees
  • Graphs
  • محركات الألعاب
  • أنظمة التشغيل

كيف تعمل الذاكرة؟

عندما تكتب:

int x = 10;

يقوم النظام بحجز مساحة في الذاكرة لتخزين الرقم 10.

مثال توضيحي:

Address      Value
1000         10

المتغير x يشير إلى هذا المكان.


المشكلة مع الذاكرة العادية

عندما تكتب:

int numbers[100];

فإن النظام يحجز مساحة لـ100 عنصر مباشرة.

حتى لو استخدمت 5 عناصر فقط.

وهذا قد يسبب هدراً في الذاكرة.


ما هي الذاكرة الديناميكية؟

هي ذاكرة يتم حجزها أثناء تشغيل البرنامج حسب الحاجة.

مثال:

إذا احتاج المستخدم 100 عنصر نحجز 100.

إذا احتاج 1000 عنصر نحجز 1000.


الكلمة new

تستخدم لحجز ذاكرة جديدة أثناء التشغيل.

مثال:

int* p = new int;

ماذا حدث هنا؟

  1. النظام حجز مساحة لعدد صحيح
  2. أعاد عنوان هذه المساحة
  3. تم تخزين العنوان داخل المؤشر p

إعطاء قيمة

#include <iostream>
using namespace std;

int main()
{
    int* p = new int;

    *p = 50;

    cout << *p;

    return 0;
}

شكل الذاكرة

Pointer p
    |
    V
Address 2000
Value 50

تحرير الذاكرة

بعد الانتهاء يجب حذف الذاكرة المحجوزة.

نستخدم:

delete p;

مثال كامل

#include <iostream>
using namespace std;

int main()
{
    int* p = new int;

    *p = 100;

    cout << *p << endl;

    delete p;

    return 0;
}

لماذا delete مهم؟

إذا لم تحذف الذاكرة المحجوزة فقد يحدث:

Memory Leak

أي تسرب للذاكرة.


ما هو Memory Leak؟

عندما يحجز البرنامج ذاكرة ولا يعيدها للنظام.

مثال خاطئ:

int* p = new int;

ثم ينتهي البرنامج أو يتم إنشاء آلاف المؤشرات بدون حذفها.


حجز مصفوفة ديناميكية

int* arr = new int[5];

مثال

#include <iostream>
using namespace std;

int main()
{
    int* arr = new int[5];

    for(int i = 0; i < 5; i++)
    {
        arr[i] = i + 1;
    }

    for(int i = 0; i < 5; i++)
    {
        cout << arr[i] << endl;
    }

    delete[] arr;

    return 0;
}

الفرق بين delete و delete[]

متغير واحد:

delete p;

مصفوفة:

delete[] arr;

مثال عملي

برنامج يطلب حجم المصفوفة من المستخدم.

#include <iostream>
using namespace std;

int main()
{
    int size;

    cout << "Enter size: ";
    cin >> size;

    int* arr = new int[size];

    for(int i = 0; i < size; i++)
    {
        cin >> arr[i];
    }

    cout << "\nValues:\n";

    for(int i = 0; i < size; i++)
    {
        cout << arr[i] << endl;
    }

    delete[] arr;

    return 0;
}

المؤشرات المتعددة

مؤشر يشير إلى مؤشر.

int x = 10;

int* p = &x;

int** pp = &p;

شرح

pp ---> p ---> x

مثال

#include <iostream>
using namespace std;

int main()
{
    int x = 10;

    int* p = &x;

    int** pp = &p;

    cout << **pp;

    return 0;
}

الناتج

10

الفرق بين Stack و Heap

Stack

تُخزن فيها المتغيرات العادية.

int x = 5;

Heap

تُخزن فيها البيانات المحجوزة بواسطة new.

int* p = new int;

مقارنة

Stack Heap
سريع أبطأ قليلاً
تلقائي يدوي
محدود أكبر حجماً
يحذف تلقائياً يحتاج delete

مشكلة Dangling Pointer

مثال:

int* p = new int;

delete p;

cout << *p;

هذا خطأ لأن المؤشر يشير إلى ذاكرة تم حذفها.


الحل

delete p;
p = nullptr;

ما هو nullptr؟

يعني أن المؤشر لا يشير إلى أي مكان.

int* p = nullptr;

مشروع عملي

إنشاء قائمة أرقام بحجم يحدده المستخدم

#include <iostream>
using namespace std;

int main()
{
    int size;

    cout << "How many numbers? ";
    cin >> size;

    int* numbers = new int[size];

    for(int i = 0; i < size; i++)
    {
        cin >> numbers[i];
    }

    cout << "\nNumbers:\n";

    for(int i = 0; i < size; i++)
    {
        cout << numbers[i] << endl;
    }

    delete[] numbers;

    return 0;
}

نصيحة مهمة

في C++ الحديثة غالباً نستخدم:

vector<int>

بدلاً من:

new
delete

لأن Vector يدير الذاكرة تلقائياً.

لكن يجب أن تتعلم new و delete لفهم كيفية عمل اللغة داخلياً.


أخطاء شائعة

❌ نسيان delete

❌ استخدام delete بدلاً من delete[]

❌ استخدام مؤشر بعد حذفه

❌ عدم تعيين nullptr بعد الحذف


تمارين

التمرين 1

احجز عدداً صحيحاً باستخدام new واطبعه.


التمرين 2

احجز مصفوفة من 10 عناصر وأدخل قيماً فيها.


التمرين 3

اطلب من المستخدم تحديد حجم المصفوفة.


التمرين 4

جرّب مؤشراً لمؤشر (pointer to pointer).


التمرين 5

اكتب برنامج يحسب مجموع عناصر مصفوفة ديناميكية.


ملخص الحلقة الرابعة

في هذه الحلقة تعلمنا:

  • Dynamic Memory
  • new
  • delete
  • delete[]
  • Heap
  • Stack
  • Memory Leak
  • Dangling Pointer
  • nullptr
  • Pointer to Pointer

في الحلقة الخامسة من المستوى المتوسط سنتعلم:

🔥 البرمجة الكائنية المتوسطة (OOP Advanced)

وسندرس:

  • Inheritance بشكل احترافي
  • Polymorphism
  • Virtual Functions
  • Abstract Classes
  • بناء نظام مستخدمين حقيقي باستخدام OOP

وهذه من أهم المراحل قبل الانتقال إلى المستوى المتقدم. 🚀

تعليقات

💬 🙋🏻‍♂️