Transcript 674387937x
Slide 1
Slide 2
إن ذاكرة الحاسب هي عبارة عن مصفوفة من البايتات .
المتحول : variableهو مكان في الذاكرة نحفظ فيه قيمة محرفية أو رقمية
أو غير ذلك ،ويختلف حجم هذا المتحول على حسب نوعه فقد يكون حجمه
بايت واحد فقط في حال كان من النمط ، charويكون حجمه 4 bytesفي
حال كان من النمط ، integerوهكذا ....
فإننا عندما نقوم بحجز متحول من النمط integerفإنه يتم حجز 4 bytes
له في الذاكرة .
Slide 3
أما عندما نقوم بتعريف متحول من النمط charفإنه يتم حجز بايت واحد
فقط له .
وعندما نقوم بإنشاء متحول من صف ما object from classفإن هذا
المتحول سيأخذ حجماً في الذاكرة يناسب الصف المعرف .
Slide 4
إن كل متحول في الذاكرة له عنوان ،للحصول على عنوان متحول ما
نستخدم العالمة & ونتبعها باسم المتحول .
مثال :ليكن المتحول xمن النمط integerويحمل القيمة 10أي :
)( 10
)(0x1BFE9C
int
;x = 10
; cout<;cout<<&x<
ال يمكن التعديل على عنوان متحول ما ،أي أن الكتابة التالية هي خاطئة :
;&x = 11
)(Error
Slide 5
أمثلة عن تعريف المتحوالت
وكيفية الحجز بالذاكرة ،وكيفية
معرفة عناوين المتحوالت
Slide 6
االسم المستعار rهو اسم مرادف لمتغير آخر .
إذا طلبت المتحول rكأنني طلبت المتحول nويكون لهما نفس المكان في الذاكرة .
Slide 7
إن rو nلهما مكان واحد في الذاكرة وإن التعامل مع أحدهم يعني كأننا
نتعامل مع اآلخر ،فإن إنقاص أحدهم يؤدي حتماً إلى إنقاص اآلخر .
Slide 8
المؤشر : pointerهو أيضاً مكان في الذاكرة ولكنه يحوي عنوان
) (addressمتحول آخر(وهي قيمة عددية مكتوبة بالنظام الست عشري
وتمثل عنوان متحول ما في الذاكرة) ،ودائماً يكون حجم المؤشر 4 bytes
مهما كان محتواه .
إن المؤشرات تعطي لغة c++فاعلية وسرعة كبيرتين.
ولكن إن التفكير والعمل بالمؤشرات يتطلب الدقة والحذر .
Slide 9
إن المؤشرات تمكننا من إنشاء أغراض أثناء الـ . Runtime
حيث إننا سابقاً كنا نقوم بتعريف مصفوفة حصراً طولها ثابت :
; ]int vector[5
أما إذا كتبنا التالي :
)(Error
; int i
;cin>>i
; ]int vector[i
Slide 10
عن طريق المؤشرات يمكننا بناء أنماط معطيات جديدة مثل :
)(Tree , Stack , Queue , linked list , …..
المؤشرات تمكننا من تمرير متحول إلى تابع على أنه متحول دخل وخرج
معا ،حيث يمكننا التعديل على المتحول داخل التابع ،وبعد الخروج من
التابع نجد أن قيمة المتحول قد تغيرت عمّا كانت عليه قبل استدعاء التابع .
Slide 11
يتم تعريف المؤشر تبعاً للصيغة التالية :
أمثلة :
Slide 12
يتم إعطاء قيمة ابتدائية للمؤشر عن طريق :
إن
NULLهي معرفة في المكتبتين
>
وهنا ال يشير المؤشر إلى أي موقع في الذاكرة.
and
>
Slide 13
يجب أن يكون نمط المؤشر من نفس نمط المعطيات التي يشير عليها كما في المثال
السابق ،أما الكتابة التالية فهي خاطئة :
تنويه:
إن تعريف المؤشر قد يكون بأحد األشكال التالية :
Slide 14
مثال :
وهنا المؤشر yPtrيحوي عنوان المتحول yوبالتالي فإنه يشير إلى المتحول . y
Slide 15
مثال آخر :
Slide 16
مثال آخر :
نالحظ أن قيمة المؤشر pهي عنوان المتحول . a
وبما أن المؤشر pهو متحول وبالتالي فإنه له عنوان نحصل عليه بكتابة . &p
Slide 17
يمكن الوصول إلى قيمة المتحول الذي يشير إليه المؤشر pعن طريق استخدام . *p
يسمى المعامل *
بـ
Dereferencing
Operator
وتسمى العملية بـ
Dereferencing
Slide 18
يمكن الوصول إلى قيمة المتحول الذي يشير إليه المؤشر pعن طريق استخدام . *p
احذر استعمال *pفي حال كان المؤشر ال يشير إلى شيء أي في حال كان يحوي
. Null
ولنتجنب حدوث األخطاء نستخدم التالي :
Slide 19
Slide 20
Slide 21
Slide 22
Slide 23
Slide 24
Slide 25
تذكر أن قيمة المؤشر هي عنوان متحول وليس قيمة ما ! .
وتذكر أيضاً أن استخدام *pتعني قيمة المتحول الذي يشير إليه
المؤشر pلذلك تجنب استعمال هذا التعبير *pفي حال كان المؤشر ال
يشير إلى شيء أي ). (NULL
Slide 26
Slide 27
Slide 28
Slide 29
ما هو الفرق بين التعبيرين *p1 = *p2
و
p1 = p2
?
التعبير األول *p1 = *p2 :معناه وضع في المتحول الذي يشير إليه
p1نفس قيمة المتحول الذي يشير إليه . p2
التعبير الثاني p1 = p2 :معناه جعل قيمة المؤشر p1نفس قيمة المؤشر
p2أي يمكننا القول أيضاً جعل p1يشير إلى المكان الذي يشير إليه . p2
Slide 30
ما هو الفرق بين التعبيرين *p1 = *p2
و
p1 = p2
?
Slide 31
ما هو الفرق بين التعبيرين ) if ( *p1 == *p2و ) ? if ( p1 == p2
التعبير األول if ( *p1 == *p2 ) :معناه هل قيمة المتحول الذي يشير إليه p1
تساوي قيمة المتحول الذي يشير إليه . p2
التعبير الثاني if ( p1 == p2 ) :هل قيمة المؤشر p1هي نفس قيمة المؤشر p2
أي يمكننا القول أيضاً هل المؤشران p1و p2يشيران إلى نفس المكان في الذاكرة...
تذكر أن قيمة مؤشر ما هي عنوان في الذاكرة .
Slide 32
يوجد ثالث طرق لتمرير المتحوالت إلى تابع
وهي :
التمرير بالقيمة . by value
التمرير بالمرجع عن طريق العناوين (وسطاء التابع هي عناوين) .
التمرير بالمرجع عن طريق المؤشرات (وسطاء التابع هي مؤشرات).
Slide 33
الطريقة األولى :التمرير بالقيمة by value
هنا يكون متحوالت
التابع هي متحوالت دخل
فقط حيث أنه بعد الخروج
من التابع تعود المتحوالت
إلى قيمها قبل االستدعاء
.
Slide 34
الطريقة الثانية :التمرير بالمرجع عن طريق العناوين (وسطاء التابع هي عناوين)
هنا يكون متحوالت التابع
هي متحوالت دخل وخرج
حيث أنه بعد الخروج من
التابع تكون المتحوالت قد تم
تعديل قيمها .
Slide 35
الطريقة الثالثة :التمرير بالمرجع عن طريق المؤشرات (وسطاء التابع هي مؤشرات)
هنا يكون متحوالت التابع
هي متحوالت دخل وخرج
حيث أنه بعد الخروج من
التابع تكون المتحوالت قد تم
تعديل قيمها .
انتبه إلى االستدعاء.
Slide 36
بعد الخروج من التابع يزول المتحول
المحلي xولكن قيمته تبقى موجودة في
الذاكرة .
ولكن هنا ال يمكننا الوصول إلى القيمة
5الموجودة في الذاكرة ألننا ال نعلم موقع
الذاكرة التي وضعت فيها أي أننا ال نعلم
عنوان المتحول xبعد الخروج من التابع .
Slide 37
بعد الخروج من التابع يزول المتحول المحلي
xولكن قيمته تبقى موجودة في الذاكرة .
المؤشر pيبقى يشير إلى مكان في الذاكرة
يحوي القيمة . 5
يمكن التعديل على القيمة الموجودة في مكان
الذاكرة الذي يشير إليه المؤشر pعن طريق الـ
. Dereferencing Operator
نتيجة البرنامج هي . 6
Slide 38
بعد استدعاء التابع والخروج منه نجد
أن المتحول xيزول ولكن قيمته تبقى
موجودة في الذاكرة ويمكن الوصول إليها
بواسطة المؤشر . p
إن السطر (*p)++يؤدي إلى زيادة قيمة
المتحول الذي يشير إليه المؤشر . p
نتيجة البرنامج هي . 6
Slide 39
يجب عند تعريف مرجع ما إعطاءه قيمة ابتدائية مباشرة .
يجب عدم استعمال الـ Dereferencing Operatorمع مؤشر يؤشر
إلى الشيء .
Slide 40
إن المؤشر pيشير إلى المتحول n
إن rهو اسم مستعار للمتحول الذي
يحوي القيمة *pأي أنه اسم مستعار
للمتحول . n
إن * و & تعمالن عمالن متعاكسان فإن :
و
n == *p
p == &n
ويمكن التعبير عن ذلك أيضاً بـً :
n == *&n
و
p == &*p
Slide 41
إذا قمنا بتعريف متحول ما على أنه constثم قمنا بتعديله فإنه سيظهر لنا
. Compiler Error
عند تعريف أي متحول على أنه constيجب إعطاءه قيمة ابتدائية مباشرة
وال يمكن أبداً تعديلها وإن محاولة تعديلها سيظهر خطأ Compiler
. Error
تذكر دائماً أن بعد المصفوفة هو ثابت سواء كان متحول تم التصريح عنه
على أنه constأو كان قيمة عددية ثابتة.
Slide 42
الحجز الديناميكي باستخدام المؤشرات
Dynamic Allocation
Using Pointers
Slide 43
نحن معتادون على الحجز الستاتيكي في الذاكرة . static allocation
حيث أن أبعاد المصفوفة هو ثابت يكون معروف مسبقاً وبالتالي هنا يتم
الحجز في الذاكرة أثناء مرحلة الـ . Compiling
إذا أردنا أن يكون حجم المصفوفة متغير أي أنه غير معروف مسبقاً
فإننا سنلجأ الستخدام الحجز الديناميكي dynamic allocation
وهنا يتم الحجز في الذاكرة أثناء مرحلة الـ . Runtime
Slide 44
عندما نقوم بإنشاء أغراض أثناء الـ . Runtime
عندما نقوم بإنشاء مصفوفات بأبعاد غير معروفة مسبقاً حيث يتم معرفة حجم
المصفوفة أثناء التنفيذ فمثالً قد يدخل المستخدم حجم المصفوفة من لوحة المفاتيح .
الحجز الديناميكي يُمكننا من التعامل مع الذاكرة بشكل أقرب حيث يمكننا أن نحرر ما
تم حجزه في الذاكرة أثناء الـ Runtimeقبل االنتهاء من تنفيذ البرنامج .
Slide 45
إذاً هناك نوعين للحجز في الذاكرة :
الحجز الستاتيكي :static allocation
يتم تعريف المتحول عند التصريح عنه مثالً . int x = 3
يتم إزالة المتحول بعد الخروج من مجاله أي بعد الخروج من .Local Block
الحجز الديناميكي ) dynamic allocationويتم باستخدام المؤشرات(:
يتم تعريف المتحول عن طريق التعليمة . new
يتم إزالة المتحول عن طريق التعليمة . delete
Slide 46
Slide 47
إن التعليمة newمتبوعة بنمط معطيات ما تقوم بالتالي :
تقوم بإنشاء مكان في الذاكرة وفقاً للنمط المذكور .
تعيد التعليمة newعنوان مكان الذاكرة السابق ،فإذا كنا نريد أن
نصل إلى مكان الذاكرة الذي تم حجزه فإن يجب علينا أن نصرح على
مؤشر ونجعله يشير إلى ذلك المكان في الذاكرة وبالتالي يصبح لدينا :
Slide 48
ويمكن الكتابة أيضاً على مرحلتين كما في المثال التالي :
تتم عملية الحجز الديناميكية في مكان في الذاكرة يدعى heapالكومة .
عند التصريح عن التعليمة
أي حجز مكان في الكومة بحجم أربعة بايتات ،فإذا
كان هناك متسع في الذاكرة بهذا الحجم تتم عملية الحجز بنجاح وترد التعليمة newعنوان مكان الذاكرة
الذي تم به الحجز ،وإال فإن قيمة المؤشر تكون NULLأي أن المؤشر ال يشير إلى شيء .
Slide 49
في المثال السابق تم حجز مكان في الذاكرة للنمط integerوتم إنشاء
مؤشر اسمه pوجعلنا pيشير إلى ذلك المكان في الذاكرة من دون أن نضع
قيمة ابتدائية في ذلك المكان في الذاكرة وهذا هو االستخدام األول للتعليمة
. new
Slide 50
في المثال السابق تم حجز مكان في الذاكرة للنمط integerوتم إنشاء
مؤشر اسمه pوجعلنا pيشير إلى ذلك المكان في الذاكرة ،وتم وضع
القيمة 5في ذلك المكان في الذاكرة وهذا هو االستخدام الثاني للتعليمة new
.
Slide 51
في المثال السابق تم حجز مكان في الذاكرة لمصفوفة من النمط integerوتم إنشاء
مؤشر اسمه pوجعلنا pيشير إلى أول عنصر في المصفوفة ،ويتم وضع قيم عشوائية
في خانات المصفوفة ،وباستخدام هذه الطريقة يمكننا إنشاء مصفوفات بأبعاد متغيرة )أي
هنا يمكن أن يكون بُعد المصفوفة متغير( ،وهذا هو االستخدام الثالث للتعليمة . new
Slide 52
في السطر األول يتم تخصيص الذاكرة للمتحول المسمى xأثناء الـ . Compile
في السطر الثاني يتم تخصيص مكان في الذاكرة لمتحول غير مسمى وجعلنا المؤشر
pيشير إلى ذلك المكان في ذلك ،وكل هذا يحصل أثناء الـ ، Runtimeونتذكر بأننا
يمكننا الوصول إلى محتوى ذلك المكان في الذاكرة عن طريق الـ . *p
Slide 53
إن التعليمة deleteمتبوعة باسم مؤشر ما تقوم بالتالي :
Slide 54
إن التعليمة deleteتقوم بـ :
تحرير مكان الذاكرة المحجوز في الكومة أي يتم حذف القيم التي كان
موجودة في ذلك المكان في الذاكرة .
إن التعليمة deleteال ترد شي .
إن التعليمة deleteتعمل عكس عمل التعليمة . new
Slide 55
Slide 56
Slide 57
Slide 58
يمكن إنشاء مكان في الكومة دون وضع قيمة فيه عن طريق:
new int
) ( new int
وفي كال الحالتين يتم وضع قيمة عشوائية في المكان المحجوز .
ذكرنا بأنه عند إنشاء مكان في الذاكرة بشكل ديناميكي قد ال يكون هناك
متسع في الذاكرة وهنا التعليمة new intترد القيمة . NULL
Slide 59
هنا نقوم بالتأكد من أنه تمت عملية إنشاء المكان في الذاكرة بشكل
صحيح عن طريق فحص إذا كان المؤشر قيمته . NULL
Slide 60
عملية التسرب في الذاكرة تحصل عندما يتم حجز في الذاكرة بشكل ديناميكي دون أن
يتم إلغاء الحجز فالقيمة 3تبقى موجودة في الذاكرة دون إمكانية الوصول إليها.
Slide 61
عملية التسرب في
الذاكرة تحصل عندما
يتم حجز في الذاكرة
بشكل ديناميكي دون أن
يتم إلغاء الحجز .
ما الحل ؟؟
; delete ptr
Slide 62
try it
Slide 63
b is 5
Slide 64
b is -8415113
Slide 65
*iPtr is 5
Slide 66
Slide 2
إن ذاكرة الحاسب هي عبارة عن مصفوفة من البايتات .
المتحول : variableهو مكان في الذاكرة نحفظ فيه قيمة محرفية أو رقمية
أو غير ذلك ،ويختلف حجم هذا المتحول على حسب نوعه فقد يكون حجمه
بايت واحد فقط في حال كان من النمط ، charويكون حجمه 4 bytesفي
حال كان من النمط ، integerوهكذا ....
فإننا عندما نقوم بحجز متحول من النمط integerفإنه يتم حجز 4 bytes
له في الذاكرة .
Slide 3
أما عندما نقوم بتعريف متحول من النمط charفإنه يتم حجز بايت واحد
فقط له .
وعندما نقوم بإنشاء متحول من صف ما object from classفإن هذا
المتحول سيأخذ حجماً في الذاكرة يناسب الصف المعرف .
Slide 4
إن كل متحول في الذاكرة له عنوان ،للحصول على عنوان متحول ما
نستخدم العالمة & ونتبعها باسم المتحول .
مثال :ليكن المتحول xمن النمط integerويحمل القيمة 10أي :
)( 10
)(0x1BFE9C
int
;x = 10
; cout<
ال يمكن التعديل على عنوان متحول ما ،أي أن الكتابة التالية هي خاطئة :
;&x = 11
)(Error
Slide 5
أمثلة عن تعريف المتحوالت
وكيفية الحجز بالذاكرة ،وكيفية
معرفة عناوين المتحوالت
Slide 6
االسم المستعار rهو اسم مرادف لمتغير آخر .
إذا طلبت المتحول rكأنني طلبت المتحول nويكون لهما نفس المكان في الذاكرة .
Slide 7
إن rو nلهما مكان واحد في الذاكرة وإن التعامل مع أحدهم يعني كأننا
نتعامل مع اآلخر ،فإن إنقاص أحدهم يؤدي حتماً إلى إنقاص اآلخر .
Slide 8
المؤشر : pointerهو أيضاً مكان في الذاكرة ولكنه يحوي عنوان
) (addressمتحول آخر(وهي قيمة عددية مكتوبة بالنظام الست عشري
وتمثل عنوان متحول ما في الذاكرة) ،ودائماً يكون حجم المؤشر 4 bytes
مهما كان محتواه .
إن المؤشرات تعطي لغة c++فاعلية وسرعة كبيرتين.
ولكن إن التفكير والعمل بالمؤشرات يتطلب الدقة والحذر .
Slide 9
إن المؤشرات تمكننا من إنشاء أغراض أثناء الـ . Runtime
حيث إننا سابقاً كنا نقوم بتعريف مصفوفة حصراً طولها ثابت :
; ]int vector[5
أما إذا كتبنا التالي :
)(Error
; int i
;cin>>i
; ]int vector[i
Slide 10
عن طريق المؤشرات يمكننا بناء أنماط معطيات جديدة مثل :
)(Tree , Stack , Queue , linked list , …..
المؤشرات تمكننا من تمرير متحول إلى تابع على أنه متحول دخل وخرج
معا ،حيث يمكننا التعديل على المتحول داخل التابع ،وبعد الخروج من
التابع نجد أن قيمة المتحول قد تغيرت عمّا كانت عليه قبل استدعاء التابع .
Slide 11
يتم تعريف المؤشر تبعاً للصيغة التالية :
أمثلة :
Slide 12
يتم إعطاء قيمة ابتدائية للمؤشر عن طريق :
إن
NULLهي معرفة في المكتبتين
>
وهنا ال يشير المؤشر إلى أي موقع في الذاكرة.
and
>
Slide 13
يجب أن يكون نمط المؤشر من نفس نمط المعطيات التي يشير عليها كما في المثال
السابق ،أما الكتابة التالية فهي خاطئة :
تنويه:
إن تعريف المؤشر قد يكون بأحد األشكال التالية :
Slide 14
مثال :
وهنا المؤشر yPtrيحوي عنوان المتحول yوبالتالي فإنه يشير إلى المتحول . y
Slide 15
مثال آخر :
Slide 16
مثال آخر :
نالحظ أن قيمة المؤشر pهي عنوان المتحول . a
وبما أن المؤشر pهو متحول وبالتالي فإنه له عنوان نحصل عليه بكتابة . &p
Slide 17
يمكن الوصول إلى قيمة المتحول الذي يشير إليه المؤشر pعن طريق استخدام . *p
يسمى المعامل *
بـ
Dereferencing
Operator
وتسمى العملية بـ
Dereferencing
Slide 18
يمكن الوصول إلى قيمة المتحول الذي يشير إليه المؤشر pعن طريق استخدام . *p
احذر استعمال *pفي حال كان المؤشر ال يشير إلى شيء أي في حال كان يحوي
. Null
ولنتجنب حدوث األخطاء نستخدم التالي :
Slide 19
Slide 20
Slide 21
Slide 22
Slide 23
Slide 24
Slide 25
تذكر أن قيمة المؤشر هي عنوان متحول وليس قيمة ما ! .
وتذكر أيضاً أن استخدام *pتعني قيمة المتحول الذي يشير إليه
المؤشر pلذلك تجنب استعمال هذا التعبير *pفي حال كان المؤشر ال
يشير إلى شيء أي ). (NULL
Slide 26
Slide 27
Slide 28
Slide 29
ما هو الفرق بين التعبيرين *p1 = *p2
و
p1 = p2
?
التعبير األول *p1 = *p2 :معناه وضع في المتحول الذي يشير إليه
p1نفس قيمة المتحول الذي يشير إليه . p2
التعبير الثاني p1 = p2 :معناه جعل قيمة المؤشر p1نفس قيمة المؤشر
p2أي يمكننا القول أيضاً جعل p1يشير إلى المكان الذي يشير إليه . p2
Slide 30
ما هو الفرق بين التعبيرين *p1 = *p2
و
p1 = p2
?
Slide 31
ما هو الفرق بين التعبيرين ) if ( *p1 == *p2و ) ? if ( p1 == p2
التعبير األول if ( *p1 == *p2 ) :معناه هل قيمة المتحول الذي يشير إليه p1
تساوي قيمة المتحول الذي يشير إليه . p2
التعبير الثاني if ( p1 == p2 ) :هل قيمة المؤشر p1هي نفس قيمة المؤشر p2
أي يمكننا القول أيضاً هل المؤشران p1و p2يشيران إلى نفس المكان في الذاكرة...
تذكر أن قيمة مؤشر ما هي عنوان في الذاكرة .
Slide 32
يوجد ثالث طرق لتمرير المتحوالت إلى تابع
وهي :
التمرير بالقيمة . by value
التمرير بالمرجع عن طريق العناوين (وسطاء التابع هي عناوين) .
التمرير بالمرجع عن طريق المؤشرات (وسطاء التابع هي مؤشرات).
Slide 33
الطريقة األولى :التمرير بالقيمة by value
هنا يكون متحوالت
التابع هي متحوالت دخل
فقط حيث أنه بعد الخروج
من التابع تعود المتحوالت
إلى قيمها قبل االستدعاء
.
Slide 34
الطريقة الثانية :التمرير بالمرجع عن طريق العناوين (وسطاء التابع هي عناوين)
هنا يكون متحوالت التابع
هي متحوالت دخل وخرج
حيث أنه بعد الخروج من
التابع تكون المتحوالت قد تم
تعديل قيمها .
Slide 35
الطريقة الثالثة :التمرير بالمرجع عن طريق المؤشرات (وسطاء التابع هي مؤشرات)
هنا يكون متحوالت التابع
هي متحوالت دخل وخرج
حيث أنه بعد الخروج من
التابع تكون المتحوالت قد تم
تعديل قيمها .
انتبه إلى االستدعاء.
Slide 36
بعد الخروج من التابع يزول المتحول
المحلي xولكن قيمته تبقى موجودة في
الذاكرة .
ولكن هنا ال يمكننا الوصول إلى القيمة
5الموجودة في الذاكرة ألننا ال نعلم موقع
الذاكرة التي وضعت فيها أي أننا ال نعلم
عنوان المتحول xبعد الخروج من التابع .
Slide 37
بعد الخروج من التابع يزول المتحول المحلي
xولكن قيمته تبقى موجودة في الذاكرة .
المؤشر pيبقى يشير إلى مكان في الذاكرة
يحوي القيمة . 5
يمكن التعديل على القيمة الموجودة في مكان
الذاكرة الذي يشير إليه المؤشر pعن طريق الـ
. Dereferencing Operator
نتيجة البرنامج هي . 6
Slide 38
بعد استدعاء التابع والخروج منه نجد
أن المتحول xيزول ولكن قيمته تبقى
موجودة في الذاكرة ويمكن الوصول إليها
بواسطة المؤشر . p
إن السطر (*p)++يؤدي إلى زيادة قيمة
المتحول الذي يشير إليه المؤشر . p
نتيجة البرنامج هي . 6
Slide 39
يجب عند تعريف مرجع ما إعطاءه قيمة ابتدائية مباشرة .
يجب عدم استعمال الـ Dereferencing Operatorمع مؤشر يؤشر
إلى الشيء .
Slide 40
إن المؤشر pيشير إلى المتحول n
إن rهو اسم مستعار للمتحول الذي
يحوي القيمة *pأي أنه اسم مستعار
للمتحول . n
إن * و & تعمالن عمالن متعاكسان فإن :
و
n == *p
p == &n
ويمكن التعبير عن ذلك أيضاً بـً :
n == *&n
و
p == &*p
Slide 41
إذا قمنا بتعريف متحول ما على أنه constثم قمنا بتعديله فإنه سيظهر لنا
. Compiler Error
عند تعريف أي متحول على أنه constيجب إعطاءه قيمة ابتدائية مباشرة
وال يمكن أبداً تعديلها وإن محاولة تعديلها سيظهر خطأ Compiler
. Error
تذكر دائماً أن بعد المصفوفة هو ثابت سواء كان متحول تم التصريح عنه
على أنه constأو كان قيمة عددية ثابتة.
Slide 42
الحجز الديناميكي باستخدام المؤشرات
Dynamic Allocation
Using Pointers
Slide 43
نحن معتادون على الحجز الستاتيكي في الذاكرة . static allocation
حيث أن أبعاد المصفوفة هو ثابت يكون معروف مسبقاً وبالتالي هنا يتم
الحجز في الذاكرة أثناء مرحلة الـ . Compiling
إذا أردنا أن يكون حجم المصفوفة متغير أي أنه غير معروف مسبقاً
فإننا سنلجأ الستخدام الحجز الديناميكي dynamic allocation
وهنا يتم الحجز في الذاكرة أثناء مرحلة الـ . Runtime
Slide 44
عندما نقوم بإنشاء أغراض أثناء الـ . Runtime
عندما نقوم بإنشاء مصفوفات بأبعاد غير معروفة مسبقاً حيث يتم معرفة حجم
المصفوفة أثناء التنفيذ فمثالً قد يدخل المستخدم حجم المصفوفة من لوحة المفاتيح .
الحجز الديناميكي يُمكننا من التعامل مع الذاكرة بشكل أقرب حيث يمكننا أن نحرر ما
تم حجزه في الذاكرة أثناء الـ Runtimeقبل االنتهاء من تنفيذ البرنامج .
Slide 45
إذاً هناك نوعين للحجز في الذاكرة :
الحجز الستاتيكي :static allocation
يتم تعريف المتحول عند التصريح عنه مثالً . int x = 3
يتم إزالة المتحول بعد الخروج من مجاله أي بعد الخروج من .Local Block
الحجز الديناميكي ) dynamic allocationويتم باستخدام المؤشرات(:
يتم تعريف المتحول عن طريق التعليمة . new
يتم إزالة المتحول عن طريق التعليمة . delete
Slide 46
Slide 47
إن التعليمة newمتبوعة بنمط معطيات ما تقوم بالتالي :
تقوم بإنشاء مكان في الذاكرة وفقاً للنمط المذكور .
تعيد التعليمة newعنوان مكان الذاكرة السابق ،فإذا كنا نريد أن
نصل إلى مكان الذاكرة الذي تم حجزه فإن يجب علينا أن نصرح على
مؤشر ونجعله يشير إلى ذلك المكان في الذاكرة وبالتالي يصبح لدينا :
Slide 48
ويمكن الكتابة أيضاً على مرحلتين كما في المثال التالي :
تتم عملية الحجز الديناميكية في مكان في الذاكرة يدعى heapالكومة .
عند التصريح عن التعليمة
أي حجز مكان في الكومة بحجم أربعة بايتات ،فإذا
كان هناك متسع في الذاكرة بهذا الحجم تتم عملية الحجز بنجاح وترد التعليمة newعنوان مكان الذاكرة
الذي تم به الحجز ،وإال فإن قيمة المؤشر تكون NULLأي أن المؤشر ال يشير إلى شيء .
Slide 49
في المثال السابق تم حجز مكان في الذاكرة للنمط integerوتم إنشاء
مؤشر اسمه pوجعلنا pيشير إلى ذلك المكان في الذاكرة من دون أن نضع
قيمة ابتدائية في ذلك المكان في الذاكرة وهذا هو االستخدام األول للتعليمة
. new
Slide 50
في المثال السابق تم حجز مكان في الذاكرة للنمط integerوتم إنشاء
مؤشر اسمه pوجعلنا pيشير إلى ذلك المكان في الذاكرة ،وتم وضع
القيمة 5في ذلك المكان في الذاكرة وهذا هو االستخدام الثاني للتعليمة new
.
Slide 51
في المثال السابق تم حجز مكان في الذاكرة لمصفوفة من النمط integerوتم إنشاء
مؤشر اسمه pوجعلنا pيشير إلى أول عنصر في المصفوفة ،ويتم وضع قيم عشوائية
في خانات المصفوفة ،وباستخدام هذه الطريقة يمكننا إنشاء مصفوفات بأبعاد متغيرة )أي
هنا يمكن أن يكون بُعد المصفوفة متغير( ،وهذا هو االستخدام الثالث للتعليمة . new
Slide 52
في السطر األول يتم تخصيص الذاكرة للمتحول المسمى xأثناء الـ . Compile
في السطر الثاني يتم تخصيص مكان في الذاكرة لمتحول غير مسمى وجعلنا المؤشر
pيشير إلى ذلك المكان في ذلك ،وكل هذا يحصل أثناء الـ ، Runtimeونتذكر بأننا
يمكننا الوصول إلى محتوى ذلك المكان في الذاكرة عن طريق الـ . *p
Slide 53
إن التعليمة deleteمتبوعة باسم مؤشر ما تقوم بالتالي :
Slide 54
إن التعليمة deleteتقوم بـ :
تحرير مكان الذاكرة المحجوز في الكومة أي يتم حذف القيم التي كان
موجودة في ذلك المكان في الذاكرة .
إن التعليمة deleteال ترد شي .
إن التعليمة deleteتعمل عكس عمل التعليمة . new
Slide 55
Slide 56
Slide 57
Slide 58
يمكن إنشاء مكان في الكومة دون وضع قيمة فيه عن طريق:
new int
) ( new int
وفي كال الحالتين يتم وضع قيمة عشوائية في المكان المحجوز .
ذكرنا بأنه عند إنشاء مكان في الذاكرة بشكل ديناميكي قد ال يكون هناك
متسع في الذاكرة وهنا التعليمة new intترد القيمة . NULL
Slide 59
هنا نقوم بالتأكد من أنه تمت عملية إنشاء المكان في الذاكرة بشكل
صحيح عن طريق فحص إذا كان المؤشر قيمته . NULL
Slide 60
عملية التسرب في الذاكرة تحصل عندما يتم حجز في الذاكرة بشكل ديناميكي دون أن
يتم إلغاء الحجز فالقيمة 3تبقى موجودة في الذاكرة دون إمكانية الوصول إليها.
Slide 61
عملية التسرب في
الذاكرة تحصل عندما
يتم حجز في الذاكرة
بشكل ديناميكي دون أن
يتم إلغاء الحجز .
ما الحل ؟؟
; delete ptr
Slide 62
try it
Slide 63
b is 5
Slide 64
b is -8415113
Slide 65
*iPtr is 5
Slide 66