• 0
LINUX MAN

ماهو الفرق بين (Call by value && call by reference)

سؤال

السلام عليكم

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

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

2 إجابة على هذا السؤال .

  • 0

:: الاستدعاء بالقيمة ( by Value ) و الاستدعاء بالمرجع ( by Reference ) ::

إذا أردنا أن ندخل مجموعة من القيم إلى داخل تابع ما .. كنا نستخدم لذلك المتحولات الوسيطة .. و عند استدعاء التابع كنا نرسل القيم التي نريدها عن طريق المتحولات الوسيطة الفعلية ( راجع فقرة المتحولات الوسيطة ) .. و لكن ما معنى الاستدعاء بالقيمة و الاستدعاء بالمرجع ؟

الاستدعاء بالقيمة ( by Value ) :

و هو الوضع الافتراضي لإرسال القيم للتوابع عن طريق المتحولات الوسيطة .. و لكن ما معناها ؟ انظر الاستدعاء التالي للتابع avr و الذي يحسب متوسط عددين ( لا يعيد قيمة ) و بفرض أن x و y هما العددين الذين سنحسب متوسطهما :

void avr(int a, int b)
{
int c = ( a+b ) / 2;
cout << c << endl;
}

void main()
{
int x, y;
x = 10; y = 20;
avr( x, y );
}

عند الاستدعاء .. سيتم إجراء نسخة عن كل من x و y و إرسالها إلى المتحولات الوسيطة a و b الخاصين بالتابع avr .. و بالتالي لن يتأثر المتغيرين x و y بنتائج عمليات التابع ( أي لن تتغير قيمتهما حتى بعد الانتهاء من التابع ) لأن المترجم قام بنسخ قيم x و y و وضعها في المتحولين الوسيطين a و b .. و بالتالي نستنتج أيضاً أنه سيتم تحميل الذاكرة بقيمتين مشابهتين تماماً لقيم x و y .

و لكن افرض مثلاً أنك تريد إرسال بيانات كبيرة ( كالكائنات أو السجلات مثلاً ) عبر تلك المتحولات الوسيطة .. فسيتم بهذه الطريقة إجراء نسخة أخرى لتلك القيم .. و بهذا سيزداد العبء على الذاكرة و سيزداد حجمها .. و لكن ما الحل لمعالجة هذه المشكلة ؟ الحل هو عن طريق الاستدعاء بالمرجع .. و تفيدنا تلك الطريقة أيضاً في إرجاع أكثر من قيمة بدلاً من قيمة واحدة فقط ( انظر الفقرة التالية ) .

الاستدعاء بالمرجع ( by Reference ) :

يختلف الاستدعاء بالمرجع عن الاستدعاء بالقيمة بأنه هذا الاستدعاء ( بالمرجع ) سيقوم بالتعامل مع عنوان المتحول الوسيط الفعلي في الذاكرة .. و بالتالي إذا حدثت أي تغييرات على المتحول الوسيط الشكلي فإن هذا التغير سيطرأ أيضاً على المتحول الوسيط الفعلي .. أي أن قيمة المتحول الوسيط الشكلي ستعطى للمتحول الوسيط الفعلي . انظروا المثال .

قاعدة / يمكنك استخدام الاستدعاء بالمرجع عن طريق وضع العلامة ( & ) قبل اسم المتحول الوسيط الشكلي الموجود في تعريف التابع .

void f1( int &a )
{
}

مثال / لتابع ندخل عليه عدد ما فيعطينا العدد الذي يليه :

void num( int &a )
{
a++;
}

void main()
{
int x;
cin >> x;
num( x );
cout << x << endl;
}

ملاحظة / لاحظ أننا لم نستخدم التوابع التي تعيد قيمة لإخراج الناتج .. بل استخدمنا الاستدعاء بالمرجع .

شرح المثال :

في هذا المثال .. سيدخل المستخدم عدد ما ( x ) ثم سنرسل هذا العدد كمرجع إلى التابع num .. و بهذه الطريقة سيتم إخراج الناتج عن طريق ( x ) أيضاً .. و لكن لن يتم هنا إجراء نسخة مطابقة للمتغير x بل سيتم تعديلها فقط عن طريق المتحول الشكلي a .. فإذا تغيرت a تتغير x و كأن a هي اسم آخر لـ x أي يتم التعامل معه و كأنه المتحول x .

و أريد التأكيد على معنى المرجعية .. قلنا فيما سبق أن المتغيرات تستخدم لتخزين قيم في الذاكرة و بالتالي لكل متغير في الذاكرة معلومتين : الأولى و هي القيمة التي يحملها .. و الثانية هي عنوانه في الذاكرة ( مكان وجوده ) .. و بالتالي عند استخدام الاستدعاء بالمرجع نكون قد وضعنا متغير آخر ( الشكلي ) يشير إلى نفس القيمة المرسلة فإذا تغيرت قيمة أحد المتغيرين ( الفعلي و الشكلي ) يكون قد تغير الأخر و كأننا وضعنا عنوانين في الذاكرة يشيران إلى نفس القيمة .. و هذا يعني أنه لن يتم نسخ قيمة المتحول الفعلي كما هو الحال في الاستدعاء بالقيمة .. حيث يتم في ذلك الاستدعاء إجراء نسخة كاملة عن المتحول الفعلي و وضعها في المتحول الشكلي بحيث يكون لها عنوان مختلف و قيمة مستقلة عن المتحول الفعلي .. و بالتالي إذا تغير أحدهم لن يتغير الأخر .

و في هذا المثال .. إذا فرضنا أن المستخدم أدخل العدد 5 فسيظهر على الشاشة العدد 6 .. و هكذا .

قاعدة 1 / من أجل القيم صغيرة الحجم يمكنك إرسال تلك القيم إلى التوابع باستخدام الاستدعاء بالقيمة .. بينما ينصح باستخدام الاستدعاء بالمرجع بالنسبة للقيمة الكبيرة .. و أيضاً من أجل إرجاع أكثر من قيمة ( أي تكون مخرجات التابع أكثر من قيمة ) .

من شرح Wolf Sniper .. أرجو أن يفيدك

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

الله يجزاك ألف خير أخوي تبسيط

مشكور وماقصرت.

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
زوار
This topic is now closed to further replies.

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .