الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

رحلتي مع المؤشرات والمرجعيات!

بدأه linuxbybelkacem في 19 مايو 2011 · 2 رد · 775 مشاهدة · في لغة C و ++C
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله تعالى وبركاته

لقد اختفيت لمدة طويلة جدا عن المنتدى وها أنا أعود وفي جعبتي حكاية جديدة :lol: :lol: ورحلة طويلة جدا جدا أشقها وحيدا وحيدا مع لغة السي++

المهم رحلتي هده المرة بدأت مع المؤشرات والمراجع والثوابت وأردت أن أشارككم ماتعلمته هده المرة قبل أن أنهيه بسؤال للأعضاء ( استفسار لم أفهمه لحد الآن )

حسنا لنبدأ :

الكل يعلم أن أهم الميزات التي تميز لغة السي ++ هي المؤشرات والمرجعيات ( أو المراجع ) الا أنه يجب أن تكون حدرا جدا في التعامل معها ( فهي كالفتاة الحسناء أو الوحش القبيح ) :P :P

المهم مهمتها هي حجز مساخة من الداكرة لمتغير ما ,استدعاء قيمة المتغير عند الحاجة وتكمن الفائدة الكبيرة في أنك عندم تججز قيمة ما وتريد تلك القيمة في عملية ما أو اسندها لمتغير جديد فالحقيقة أنك لن تحتاج لحجز مساحة جديدة للمتغير الجديد بل ستقول للمتغير الجديد ادهب الى العنوان الدي فيه القيمة مباشرة

وهي دات فائدة كبيرة خاصة عند التعامل مع المساحات الكبيرة كالملفات


string *P1 = new string("Hello") ;
string *P2 = P1 ;

cout << "Test= "<<*P1 << endl << endl ;
cout << "Test2= "<<*P2 << endl << endl ;

*P1 = "new value" ;
cout << "Test= "<<*P1 << endl << endl ;
cout << "Test2= "<<*P2 << endl << endl ;

النتائج ستكون كما يلي

P1= Hello

P2 = Hello

P1 = new value

P2 = new value

بكل بساطة في المثال السابق لم نغير من قيمة P2 ولكن قمنا بتغيير قيمة P1 فقط ولكن قيمة المؤشر الثاني أصبحت مساوية للمؤشر الأول والسبب بسيط وهو أن كلا المؤشؤين يشيران الى نفس المكان في الداكرة وبالتالي فـأي تغير في قيمة الداكر تؤثر على كل المؤشرات التي تشير الى نفس المكان وهدا رسم بسيط يشرح المثال السابق

post-131804-072749600 1305802988_thumb.p

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

حسنا أول ماسيتبادر الى أدهاننا هو الكود التالي

string get()
{
return stringname
}
[code/]

نقوم بتجريب الدالة






[code]

cout << "st= "<<st << endl << endl ;
cout << "Get= "<<Get() << endl << endl ;

g= "new string";

cout << "st= "<<st << endl << endl ;
cout << "Get= "<<Get() << endl << endl ;

النتائج كما يلي

st = Bingo

Get= Bingo

st = Bingo

Get = new String

كما لاحظتم فان قيمة st لم تتغير بالرغم من أننا غيرنا قيمة g والسبب هو أن لكل سلسلة مساحة داكرة خاصة بهما ولكن بما أننا نتلكم عن المؤشرات فالأفضل دائما أن تكون الدالة التي تعيد القيمة هي دالة تشير الى مؤشر وسأقول لكم لمادا

فلنفترض أننا في برنامج ما نريد فتح ملف والآن الملف المفتوح سيأخد مكانا في الداكرة والآن أريد أن أرسل مضمون الملف الى دالة ما مثلا تقوم بحساب عدد الكلمات أو عدد الأحرف في الملف المفتوح .

حسنا سنقول أن حجم الملف هو 20 ميغابايت باستخدام الدالة السابقة بدون استخدام المؤشرات الدالة ستقوم بنسخ الملف الى مساحة جديدة وتقوم بحساب عدد الكلمات

أي بعملية بسيطة الملف المفتوح سيأخد ضعف المساحة التي سيأخدها عند فتح الملف وكأننا فتحنا نفس الملف مرتين والآن يمكنكم تخيل القيام بعمليات أعقد من فتح الملفات قد تكلف الحاسوب كل الداكرة !!!!! نعم هدا ليس خيالا وانما هو كابوس على مستوى المشاريع المتوسطة والكبيرة

حسنا سنستيقظ من الكابوس ونجد حلا لفلم الرعب هدا !!!!! :P :P


{
return g;
}
string &Get()

حسنا مالجديد في الدالة السابقة

بطلة الرواية هده المرة هو الحرف&

هدا هو بطلنا وهو ليس القيمة and في سي++>

بل هو الأخ الشقيق للمؤشرات فعند اضافته الى الدالة أخبرنا الدالة أننا لانريد أن تعيدي لنا قيمة السلسة ولكن نريد عنوان السلسلة

أي أننا لاننسخ القيمة الى مساحة جديدة ولكن ندهب مباشرة الى عنوان القيمة

حسنا الآن فلنفترض أنه لدينا صنف وهدا الصنف لديه دالة تعيد اسم الصنف

وبما أننا فهمنا الدرس من المؤشرات والمراجع فالأفضل أن نستخدمها

هاهو تعريف الدالة

[code]string &Get()
{
return g;
}

الكود السابق صحيح ولكن دعونا نجرب الكود التالي

Get() = "new name" ;

ماذا حدث ؟؟ حسنا لقد قمنا بتغيير اسم الصنف..

المشكلة أن هذا شيء خطير جدا جدا :ohmy: :ohmy: اذ أنه من المعروف أن الأعضاء الداخلية للأصناف لايمكن تغيير قيمتها الا اذا كانت دالة صريحة داخل الصنف تقوم بتغيير القيم ةهذه الدوال تكون عادة على الشكل

set_name() , set_value()

ولكن المشكلة تكمن في أنه عندما أعادت الدالة قيمة اسم الصنف(وهو عادة عن متغير خاص لايمكن الدخول اليه من خارج الصنف ) قمت بتغيير القيمة بطريقة غير شرعية ان صح التعبير ودعونا نطبق هذا المشكل على صعيد كودي كبير يتجاوز تغيير الاسم

مثلا نأخذ مثالى عن صنف يقوم باعادة المال الموجود في حساب شخص في أحد البنوك ( القيمة عبارة عن عدد صحيح مثلا )

ونقوم بما يلي


int &Get_money()
{

return _money ;
}


دعونا نجرب التالي
[code]Get_money() = 1000000 [code/]


}

مبروك للشخص صاحب الحساب فلقد أصبح غنيا

أو يمنكنك أن تنتقم منه شر انتقا م


[code]Get_money() = 0 dollar

هل وصلت الرسالة (أعني هنا المشكلة وليس المال :lol: :lol: )

الآن كيف يمكننا أن نحمي حساب هذا الشخص

حسنا هناك 3 حلول

1- أن يقوم الجميع بسحب أموالهم والعودة الى العصر الحجري والأجر يكون نقدا : :ohmy:

2- أن يتبرعو بكل أموالهم :blink: :wacko: :excl:

3- استخدام الكلمة المفتاحية const في سي++

حسنا أعلم أنكم غاضبون مني لأني أوقفت انتقامكم من أصحاب الملايير ( آسف فأنا لدي مبادئي :wink: :wink: )

المهم سنكتب نفس الدالة ولكن بتغيير طفيف


{
return _money
}
const &Get_Money()

الآن دعونا نجرب الكود مرة أخرى

[كود]Get_money() = 10000000

[/كود]

الآن لن نسيطيع تعيير قيمة المال أبدا ( لابد من دالة داخل الصنف لكي تقوم بحساب المال الزائد أو الناقص )

ستلاحظ ظهور خطأ في المترجم وانطلاق صفارات الانذار :P

حسنا لقد قاربت حكاية جدتي على النهاية وسأخبركم بسر آخر

الأمثلة الأولى كلها خاطئة !!!!!!! :blink: :blink: :blink:

ليس على الصعيد الكودي وانما على الصعيد البرمجي يعني البرامج ستير بشكل عادي الا أن هناك خطأ مقصودا

هل تتذكرون عندما قلت لكم أن المؤشر يحجز مساحة حسنا عند انتهاء مدة استخدام المؤشر أو البرنامج ماذا تفعل :mellow: ؟؟

بكل بساطة نقوم بتحرير مساحة بواسطة الملكة delete

جربها وسترى نتائج غير مرضية

لن أخبرك عنها الآن وسأقوم بشرحها في موضوع متتم لهذا الموضوع

المرفقات
Untitled.png

تم تعديل هذه المشاركة بواسطة linuxbybelkacem في 19 مايو 2011 في 15:51

#2

آخي عندي سؤآل

متى اعرق البوينتر على انها بوينتر اف سترينق

او بوينتر اف كآركترز

؟؟؟

#3

السلام عليكم

لا أدري هل السؤال موجه للأخ linuxbybelkacem فقط, عموما .. أستأذن صاحب الموضوع للإجابة :

Une chaîne de caractère est un tableau. Un tableau de caractères, dont le dernier est '\0', le fin de chaîne.

Une chaîne peut être désignée par un pointeur (sur charactère) qui pointe lsur le premier caractère de la chaîne.

بالتوفيق.

تم تعديل هذه المشاركة بواسطة أحمد المتألق في 28 مايو 2011 في 14:42

مواضيع مشابهة