إدارة الذاكرة في ++C

إدارة الذاكرة :

رأينا أمثلة تستخدم فيها المصفوفات لكي تحجز مساحة من الذاكرة فالتعبير :

Int arr1[10];

يحجز مساحة من الذاكرة تكفي 100 من الأعداد الصحيحة . علي أنه قد توجد مواقف لا تكون فيها علي علم مسبق بالمساحة المطلوب حجزها , كأن تملأ مصفوفة عن طريق المستخدم .

تقدم لنا لغة السي ++ مؤثرا هو المؤثر new يحل هذه المشكلة .

المؤثر new

البرنامج التالي يبين لك استخدام هذا المؤثر :

newintro.cpp


 


// newintro.cpp


// introduces operator new


#include <iostream.h>


#include <string.h>     // for strcpy()


#include <conio.h>


 


void main()


   {


   char* str = "Idle hands are the devil's workshop.";


   int len = strlen(str);     // get length of str


 


   char* ptr;                 // make a pointer to char


   ptr = new char[len+1];     // set aside memory: string + '\0'


 


   strcpy(ptr, str);          // copy str to new memory area ptr


 


   cout << endl << "ptr=" << ptr;  // show that ptr is now in str


 


   delete[] ptr;              // release ptr's memory


   getche();


   }




في البرنامج تقوم العبارة :



Ptr = new char[len+1];



بحجز مساحة بقدر المتغير len (المختزن به طول المصفوفة str المعاد من الدالة ( strlen() زائد 1 للمحرف الصفري . ويبين الشكل صيغة ذلك المؤثر (لا تنس استخدام القوسين المربعين , لو استخدمت القوسين العاديين لن يعترض المترجم , ولكن النتيجة خاطئة ) وشكل حجز المساحة من الذاكرة باستخدام ذلك المؤثر .



Object-Oriented Programming in C   _Page_0486_Image_0001



شكل صيغة المؤثر new



Object-Oriented Programming in C   _Page_0486_Image_0002



شكل مساحة محجوزة بالمؤثر new



وفي البرنامج تقوم الدالة strcpy() بنسخ العبارة النصية في المساحة التي حجزها المؤثر المذكور , والذي يشير المؤشر ptr لبدايتها .



وسوف يري العارفين بلغة السي التقليدية أن المؤثر new يلعب دور الدالة malloc , ولكن أسلوب هذا المؤثر أفضل من عديد من النواحي .



أما من جهة وجود ما يقابل الدالة reallocate() للتغير في حجم المساحة المحجوزة فلا داعي لوجود ما يقابلها في السي ++ , إذ يمكنك دائما العودة لنفس المؤثر لإعادة تحديد المساحة من جديد .



المؤثر delete



لكي نضمن عدم استهلاك مساحة الذاكرة يرفق بالمؤثر new مؤثرا أخر هو delete وظيفته تحرير المساحة المحجوزة .



وقد ألحق بالمؤثر القوسان المربعان دليل علي أن المساحة المطلوب محوها هي لمصفوفة , ولضمان محو كل عناصرها , أما لو كانت المساحة لغير مصفوفة فلا يستخدم القوسان [ في بعض الأحيان لا يقبل المترجم هذين القوسين ويصدر رسالة Operand expected , في هذه الحالة أمحهما  ] .



فئة عبارة نصية بإستخدام المؤثر new



يظهر المؤثر new غالبا في بادئة , وتطبيقها لذلك سنعطي مثالا نعدل فيه البرنامج strplus المعطي في فصل 9 ولعلك تذكر أن العيب الأساسي فيه كان احتلال العبارة لمساحة محددة من الذاكرة , وأن العبارات الأقل تمثل إهدارا للمساحة كما أن العبارات الأطول تمثل خطرا علي النظام حيث ستكتب خارج المساحة المحددة ومثالنا التالي يستخدم المؤثر new لكي نحصل علي القدر اللازم فقط من المساحة .






newstr.cpp


 


// newstr.cpp


// using new to get memory for strings


#include <iostream.h>


#include <string.h>      // for strcpy(), etc


#include <conio.h>


 


class String             // user-defined string type


   {


   private:


      char* str;                    // pointer to string


   public:


      String(char* s)               // constructor, one arg


     {


     int length = strlen(s);    // length of string argument


     str = new char[length+1];  // get memory


     strcpy(str, s);            // copy argument to it


     }


      ~String()                     // destructor


     {


     delete[] str;              // release memory


     }


      void display()                // display the String


     {


     cout << str;


     }


   };


 


void main()


   {                              // uses 1-arg constructor


   String s1 = "Who knows nothing doubts nothing.";


 


   cout << endl << "s1=";         // display string


   s1.display();


   getche();


   }




الفئة string تحتوي علي عنصر بيان وحيد المؤشر المحرفي char المسمي str وهو يشير للمصفوفات المحتواة في الكائنات المنتمية للفئة . وليس في الكائن مصفوفة تحتوي علي العبارة النصية , فهي تخزن في مكان أخر أما الكائن فيحتوي علي مصفوفة بعناوين عناصر العبارة النصية .



وتقوم البادئة بتخصيص المساحة اللازمة للعبارة , ويشير str لعنوان المساحة التي تم تخصيصها . بعد ذلك تقوم البادئة باستخدام الدالة strcpy() لعملية النسخ .



وللمرة الأولي تقابل دالة منهية destructor وهي الدالة التي تستدعي أليا مع إنتهاء عمر الكائن وهي تحمل اسم الفئة مع الرمز ∼ قبله . المنهية هنا تحتوي علي أمر واحد هو المؤثر delete هو إلغاء تخصيص المساحة المحجوزة .



ونقابل مع استخدام المنهية بهذه الصورة عيبا خفيا , وهو أنه عند نسخ كائن لأخر , فإن كلا الكائنين يشيران لنفس المساحة . وحين ينتهي كائن منهم ويقوم المؤثر delete بعمله في إنهاء تخصيص المساحة المحجوزة يكون ذلك علي حساب الكائن الأخر , والذي يشير مؤشره في هذه الحالة لعناوين لم تعد سارية . وسوف نري  كيفية وضع منهيات أكثر ذكاء بعد ذلك .

التسميات: