View Full Version : Call by refrence
aidinwashere
دوشنبه 27 آذر 1385, 21:05 عصر
سلام
کد زیر چرا کار میکند؟
F1(int &a)
{
a++;
//a is inremented
}
main()
{
int a=1;
F1(a);
//here!
}
اول اینو بگم که مشکل در C++ است نه در C.
سوال اینه که وقتی من F1(a) رو صدا میزنم، دارم خوده a رو پاس میدم ولی تابع داره آدرسش رو میگیره.
دوم اینکه این چطوری By Refrence کار میکنه؟
پیشاپیش متشکرم.
Arash_j13
دوشنبه 27 آذر 1385, 22:53 عصر
چون شما ورودی تابع رو یک رفرنس گرفتید خصوصیت رفرنس ها اینکه هر تغییری توشون بدید توی متغییر اصلی هم همون تغییرات داده می شه برای تبدیل شدن به رفرنس فقط علامت & لازم هست
aidinwashere
سه شنبه 28 آذر 1385, 06:36 صبح
سلام.
مرسی از پاسختون.
درست که من رفرنس میگیرم، ولی چیزی که پاس میدم، خوده متغیره، نه آدرسش.
مگر نه اینکه برای رفرنس داشتن به یه متغیر باید "آدرس" اونو پاس داد؟
مرسی.
mzjahromi
سه شنبه 28 آذر 1385, 06:52 صبح
شما به نوع تعریف تابعتون توجه کنید. اگر تابع رو به شکل زیر تعریف کنید مقدار تغییر نمیکنه
f(int a)
ولی به شکلی که شما تعریف کردید خود کامپایلر آدرس رو پاس میده
aidinwashere
شنبه 02 دی 1385, 23:20 عصر
مرسی از پاسختون.
ولی دو سوال پیش میاد:
1- اگر آدرس را پاس میدهد، پس درتابع وقتی آدرس رو میگیرم، باید با * به محتویات اون دسترسی داشته باشم وگرنه x++ اونو به آدرس خونه بعدی حافظه منتقل میکنه.
2- مگر خاصیت C این نیست که هرکدی که کاربر میخواد رو اجرا کنه بدون دخل و تصرف؟ مثلا من یه آرایه 2خونه ای داشته باشم و بخوام به خونه 200ام دسترسی داشته باشم. اینجا هم من دارم خوده متغیر رو پاس میدم که با آدرسش متفاوته.
با تشکر، اگه میشه بیشتر توضیح بدین، اساتید ما که ...
mzjahromi
یک شنبه 03 دی 1385, 07:00 صبح
ببینید دوست عزیز
شما انتظار دارید وقتی که اسم آدرس میاد دقیقا مثل اون حالت int * a عمل کنه در صورتیکه عملا اینطور نیست. وقتی که شما یه متغیر تعریف میکنید عملا خودش یه آدرسه وقتی میگید int a خود a آدرس خونه ای هست که محتویات اون رو نگهداری میکنه و موقع کامپایل شدن جایگزین a میشه چون توی سطوح پائین که نگاه کنید اصلا اسم معنی نمیده و این اسم گذاریها کاری هست که طراح کامپایلر انجام میده واسه اینکه ما بتونیم ساده تر برنامه رو بنویسیم حالا انواع مختلف نام گذاری هم استاندارد های یه کامپایلر هست و وقتی که شما یه تابع رو به شکل F1(int &a)
تعریف میکنید یعنی میخواهید همون متغیر قبلی رو اینجا هم داشته باشید یعنی فقط اسم متغیر عوض میشه و a اشاره میکنه به همون آدرسی که متغیر اصلی اون اشاره میکرد.
نمیدونم تونستم منظورم رو بیان کنم یا نه
azizi-ra
یک شنبه 03 دی 1385, 08:21 صبح
توضیحات دوستان درست است و من سعی میکنم آنها را مرتب کنم.
ما دو روش برای کار کردن با اشارگر ها داریم
در روش اول
اشارگر به این صورت تعریف میشود.
int *a;
به این صورت مقدار دهی میشود.
a = &b;
و به این صورت در یک فانکشن استفاده میشود
void func (int *aa)
{
...
}
...
func(a)
در روش دوم کار کمی ساده تر است
این روش به reference مشهور است. البته reference ها اشارگر نیستند.
void func(&aa){
....
}
همان کاری که شما انجام دادید.
در این روش نیازی به استفاده کردن از عملگر & برای دادن آدرس به فانکشن نیست و این کامپایلر خودش متوجه کار میشود. :لبخند:
اگر باز هم متوجه متوجه نشدید به این آدرسها رجوع کنید.
reference 1 (http://www.parashift.com/c++-faq-lite/references.html#faq-8.1)
reference 2 (http://www.cprogramming.com/tutorial/references.html)
aidinwashere
یک شنبه 03 دی 1385, 10:19 صبح
مرسی از پاسخ دوستان.
جناب mzjahromi، پس اگر اینطور فرض کنم، Call By Value هم باید دقیقا کاره Call By Refrence رو انجام بده، چون مثلا:
f1(int a)
{
a++
}
main()
{
f1(int a=2)
}
پس طبق فرمایش شما اگر "وقتی که شما یه متغیر تعریف میکنید عملا خودش یه آدرسه وقتی میگید int a خود a آدرس خونه ای هست که محتویات اون رو نگهداری میکنه و موقع کامپایل شدن جایگزین a میشه" باشد و من درست متوجه شده باشم، این حالت هم آدرسه a پاس داده میشود و موقع compile جایگزینه a در تابع شده و call by refrence خواهیم داشت.
(هرچند باز دیگر سوال من مطرح میشود که اگر a همان آدرسه a است، پس a++ باید به خانه بعدی حافظه برود.)
mzjahromi
یک شنبه 03 دی 1385, 11:44 صبح
پس طبق فرمایش شما اگر "وقتی که شما یه متغیر تعریف میکنید عملا خودش یه آدرسه وقتی میگید int a خود a آدرس خونه ای هست که محتویات اون رو نگهداری میکنه و موقع کامپایل شدن جایگزین a میشه" باشد و من درست متوجه شده باشم، این حالت هم آدرسه a پاس داده میشود و موقع compile جایگزینه a در تابع شده و call by refrence خواهیم داشت.
نه اینطور نیست. محدوده نیز باید در نظر بگیرید و شکل تعریف توابع. وقتی که شما تابع را به صورت cal by value تعریف میکنید عملا دارید به کامپایلر میگید که تنها مقدار این تابع رو ارسال کن و برای اون هم مهم نیست که اسم این متغیر داخل تابع چی هست. ولی وقتی که شما به صورت Call by Reference تابعی رو تعریف میکنید آدرس متغیر جایگزین نام داخل تابع میشه حالا حتی اگر نام متفاوت باشه.
شما این رو در نظر بگیرید که کامپایلر یه استاندارد هائی رو برای شما تعریف میکنه و اگر طبق اون استاندارد ها عمل کنید مقدار اولیه متغیر تغییر میکنه یا نمیکنه که توی مدل اول Cal by reference و توی مدل دوم call by value خواهد بود در حالت اول فضای دیگری برای متغیر تعریف نمیشه ولی در حالت دوم چرا.
اگر a همان آدرسه a است، پس a++ باید به خانه بعدی حافظه برود.
نمیدونم تا چه حد با زبان ماشین (در سطح کاملا پائین نه اون اسمبلی ما) آشنا هستید. اونجا مثلا خانه 100 از سگمنت داده رو برای یک متغیر در نظر میگیرید این 100 آدرس خونه ای است که شما دارید استفاده میکنید و a برچسب یا اسم اون خونه است توجه کنید این با آدرس فرق میکنه
و اون شکل تابعی که شما توی پست اول معرفی کردید همون خونه رو به a که داخل تابع هست هم نسبت میده(که میتونه اسم دیگری هم داشته باشه).
اگر با مفاهیم کامپایلر و اسمبلی آشنائی ندارید و حرفهای من براتون مفهوم نیست بهتره تنها نحوه عملکرد و تفاوتهای ظاهری رو در نظر بگیرید
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.