أداة New وأداة Delete

وقت القراءة: 7 دقائق 77 مشاهدة

في البرمجة الكائنية (OOP) مع لغة C++، تلعب المؤشرات Pointers دورًا حاسمًا في إدارة الذاكرة والوصول إلى الكائنات ديناميكيًا. فيما يلي شرح موجز للمؤشرات في سياق OOP في C++:

تعريف:

المؤشر Pointer هو متغير يحمل عنوان الذاكرة لمتغير آخر. في لغة C++، يمكن استخدام المؤشرات لتخزين عناوين الكائنات التي تم إنشاؤها ديناميكيًا على الـheap.

مثال 1:

int main()
{
    int var1 = 11;
    int var2 = 22;
    cout << &var1 << endl;
    cout << &var2 << endl;
    
    int *ptr;
    ptr = &var2;
    *ptr = 5000;
    cout << *ptr << endl;
    cout << var2 << endl;
}

يوضح هذا الكود استخدام المؤشرات لمعالجة المتغيرات والوصول إلى عناوين الذاكرة الخاصة بها.

  1. الإعلان وتفعيل المتغير:
    int var1 = 11;
    int var2 = 22;
    

    تم الإعلان عن متغيرين صحيحين، var1 وvar2، وإعطائهما القيمتين 11 و22، على التوالي.

  2. طباعة عناوين الذاكرة:
    cout << &var1 << endl;
    cout << &var2 << endl;
    

    تتم طباعة عناوين الذاكرة var1 وvar2 باستخدام عامل تشغيل عنوان (&). يكشف هذا عن المواقع في الذاكرة حيث يتم تخزين هذه المتغيرات.

  3. إعلان المؤشر وتعيين قيمته:
    int *ptr;
    ptr = &var2;
    

    تم الإعلان عن متغير المؤشر ptr من النوع int. وتم تعيين عنوان var2 للمؤشر ptr.

  4. استخدام المؤشر لتعديل المتغير:
    *ptr = 5000;
    

    يتم تغيير القيمة التي يشير إليها ptr إلى 5000. وبما أن ptr يشير إلى عنوان var2، فإن هذا يعدل أيضًا قيمة var2.

  5. طباعة قيمة المؤشر والمتغير الذي تم تعديله:
    cout << *ptr << endl;
    cout << var2 << endl;
    

    تتم طباعة القيمة المشار إليها بواسطة ptr (5000) والقيمة المعدلة لـ var2. يجب أن تكون كلتا القيمتين متماثلتين، حيث تم استخدام المؤشر لتعديل محتوى var2.

قد تبدو مخرجات الكود كما يلي:

0x7fff5fbff628  // Memory address of var1
0x7fff5fbff624  // Memory address of var2
5000             // Value pointed to by ptr
5000             // Modified value of var2

قد تختلف عناوين وقيم الذاكرة الدقيقة وفقًا للنظام والمترجم.

تخصيص الذاكرة الديناميكية:

غالبًا ما يتضمن OOP إنشاء كائنات باستخدام عامل التشغيل new لتخصيص الذاكرة الديناميكية. تُستخدم المؤشرات لتخزين عنوان الكائنات المخصصة ديناميكيًا.

حذف الكائنات الديناميكية:

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

مثال 2:

#include <iostream>
using namespace std;

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

يوضح هذا الكود تخصيص الذاكرة الديناميكية وإلغاء التخصيص لمتغير عدد صحيح. وفيما يلي شرح للكود:

#include <iostream>
using namespace std;

int main()
{
    // Declare a pointer variable
    int *p;

    // Allocate memory for an integer on the heap
    p = new int;

    // Assign a value to the dynamically allocated integer
    *p = 10;

    // Print the address of the dynamically allocated memory
    cout << p << endl;

    // Deallocate the dynamically allocated memory
    delete p;

    return 0;
}

شرح:

  1. الإعلان عن المؤشر:
    int *p;
    

    يعلن عن متغير المؤشر p الذي سيتم استخدامه لتخزين عنوان عدد صحيح مخصص ديناميكيًا.

  2. تخصيص الذاكرة الديناميكية:
    p = new int;
    

    يخصص الذاكرة على الـheap لتخزين عدد صحيح ويعين عنوان الذاكرة المخصصة للمؤشر p.

  3. تعيين قيمة:
    *p = 10;
    

    يتم إلغاء الإشارة إلى المؤشر p وتعيين القيمة 10 للعدد الصحيح المخصص ديناميكيًا.

  4. طباعة العنوان:
    cout << p << endl;
    

    يطبع عنوان الذاكرة المخصصة ديناميكيًا. هذا العنوان موجود في الـheap وقد يختلف في كل مرة يتم فيها تشغيل البرنامج.

  5. إلغاء تخصيص الذاكرة:
    delete p;
    

    إلغاء تخصيص الذاكرة المخصصة مسبقًا بأخرى جديدة. هذه الخطوة ضرورية لمنع تسرب الذاكرة.

مثال 3:

#include <iostream>
using namespace std;

int main()
{
    // Declare two pointer variables
    int *p1, *p2;

    // Allocate memory for the first integer on the heap
    p1 = new int;
    *p1 = 10;

    // Print the location of the pointer and the content of the allocated memory
    cout << &p1 << endl; // location of the pointer
    cout << "Memory location " << p1 << "\n";
    cout << " contains " << *p1 << endl;

    // Allocate memory for the second integer on the heap
    p2 = new int;
    *p2 = 10;

    // Print the location of the second pointer and the content of the allocated memory
    cout << &p2 << endl; // location of the pointer
    cout << "Memory location " << p2 << "\n" << " contains " << *p2 << endl;

    // Deallocate the dynamically allocated memory
    delete p1;
    delete p2;

    return 0;
}

يوضح هذا الكود تخصيص الذاكرة الديناميكية لمتغيرين صحيحين باستخدام المؤشرات. وفيما يلي شرح للكود:

  1. الإعلان عن المؤشر:
    int *p1, *p2;
    

    يعلن عن متغيري المؤشر، p1 وp2، اللذين سيتم استخدامهما لتخزين عناوين الأعداد الصحيحة المخصصة ديناميكيًا.

  2. تخصيص الذاكرة الديناميكية (p1):
    p1 = new int;
    *p1 = 10;
    

    يخصص الذاكرة في الـheap لعدد صحيح باستخدام new، ويعين العنوان إلى p1، ويعين القيمة 10 للعدد الصحيح المخصص ديناميكيًا.

  3. طباعة المعلومات (p1):
    cout << &p1 << endl; // location of the pointer
    cout << "Memory location " << p1 << "\n";
    cout << " contains " << *p1 << endl;

    يطبع موقع متغير المؤشر p1 ومحتوى الذاكرة التي يشير إليها.

  4. تخصيص الذاكرة الديناميكية (p2):
    p2 = new int;
    *p2 = 10;
    

    يخصص الذاكرة في الـheap لعدد صحيح آخر باستخدام new، ويعين العنوان لـ p2، ويعين القيمة 10 للعدد الصحيح المخصص ديناميكيًا.

  5. طباعة المعلومات (p2):
    cout << &p2 << endl; // location of the pointer
    cout << "Memory location " << p2 << "\n" << " contains " << *p2 << endl;
    

    يطبع موقع متغير المؤشر p2 ومحتوى الذاكرة التي يشير إليها.

  6. إلغاء تخصيص الذاكرة:
    delete p1;
    delete p2;
    

    إلغاء تخصيص الذاكرة المخصصة ديناميكيًا باستخدام delete لتجنب تسرب الذاكرة.

مثال 4:

#include <iostream>
using namespace std;

class CRectangle 
{
        int *width, *height;
    public:
        CRectangle(int, int); //constructor
        ~CRectangle(); //destructor
        int area()
        {
            return (*width * *height);
        }
};
CRectangle::CRectangle(int a, int b)
{
    width = new int;
    height = new int;
    *width = a;
    *height = b;
}
CRectangle::~CRectangle()
{
    delete width;
    delete height;
}
int main()
{
    CRectangle rect(3, 4), rectb(5, 6);
    cout << "rect area: " << rect.area() << endl;
    cout << "rectb area: " << rectb.area() << endl;
    return 0;
}

يحدد هذا الرمز فئة CRectangle للمستطيلات باستخدام تخصيص الذاكرة الديناميكية للعرض والارتفاع. إليك تفاصيل الكود:

  1. تعريف الفئة (CRectangle):
    تمثل الفئة CRectangle مستطيلات، مع تخزين عرض وارتفاع الأعضاء الخاصين كمؤشرات أعداد صحيحة ديناميكية.
  2. أداة البناء Constructor (CRectangle::CRectangle):
    يخصص الـconstructor الذاكرة للعرض والارتفاع باستخدام new ويقوم بتهيئتهم بالقيم المقدمة.
  3. أداة الهدم Destructor (CRectangle::~CRectangle):
    يقوم الـdestructor بإلغاء تخصيص الذاكرة للعرض والارتفاع باستخدام delete.
  4. دالة العضو (area):
    تقوم دالة area بحساب مساحة المستطيل وإرجاعها باستخدام القيم المخزنة في العرض والارتفاع.
  5. الدالة الرئيسة main:
    ينشئ مثيلات CRectangle (rect and rectb) مع تخصيص الذاكرة الديناميكية للعرض والارتفاع.
    يستدعي دالة area لحساب وعرض مساحة كل مستطيل.
    يتم استدعاء أدوات التدمير تلقائيًا عندما تخرج (rect and rectb) عن النطاق، مما يؤدي إلى تحرير الذاكرة المخصصة ديناميكيًا.

 

 

مشاركة هذا

أداة New وأداة Delete

Or copy link

المحتوى
Arabic