زبان برنامهنویسی C از دو نوع متغیر پشتیبانی میکند: متغیرهای معمولی و اشارهگرها (متغیرهای حاوی آدرس حافظه). زبان ++C نوع سومی را به این مجموعه اضافه کرده است: متغیرهای مرجع (Reference).
متغیرهای مرجع از روی دو نوع دیگر ساخته میشود و به نوعی میتوان گفت نام مستعار برای متغیر اصلی به حساب میآید. برای تعریف متغیر مرجع از عملگر & استفاده میکنیم:
عبارت فوق متغیر b را مرجعی برای a معرفی میکند. از این کد به بعد متغیرهای a و b معادل هم هستند. یعنی تغییرات a در b و تغییرات b در a تاثیر میگذارد. در واقع a و b از یک محل حافظه استفاده میکنند؛ یا اینکه یک خانه حافظه، دو نام متفاوت دارد.
کاربرد اصلی متغیرهای مرجع را میتوان در انتقال اطلاعات به توابع و بالعکس دید. همانطور که میدانید در زبان C دو روش برای انتقال اطلاعات به تابع و بالعکس وجود دارد: مقدار و اشارهگر. زمانی که از روش اول استفاده میکنیم، آرگومان متناظر با پارامتر تابع فقط یک کپی از مقدار آن پارامتر را دارد. یعنی تغییر متغیر آرگومان تاثیری در متغیر پارامتر ندارد. مثلا:
void func(int a) {
a = 5;
}
void main() {
int n = 6;
func(n);
printf("%d", n);
}
زمانی که تابع func فراخوانی میشود، یک کپی از مقدار n در a قرار میگیرد (یعنی 6). تک دستور تابع func مقدار a را تغییر میدهد. این تغییر هیچ اثری در n ندارد و مقدار n همان 6 چاپ میشود. چرا که n به صورت مقدار به تابع ارسال شده است.
اگر بخواهیم از روش اشارهگر استفاده کنیم، برنامه فوق به این صورت خواهد شد:
void func(int *a) {
*a = 5;
}
void main() {
int n = 6;
func(&n);
printf ("%d", n);
}
با تغییراتی که اعمال شده، مقدار n در تابع قابل تغییر است. یعنی آخرین دستور برنامه مقدار 5 را برای n چاپ میکند.
زبان ++C علاوه بر دو روش قبلی روش سومی هم دارد. در این روش از متغیرهای مرجع استفاده میشود. مثال بالا را یک بار دیگر، این بار با متغیر مرجع مینویسم:
void func(int &a) {
a = 5;
}
void main() {
int n = 6;
func(n);
cout << n;
}
متغیر a یک مرجع برای n معرفی شده است. پس تغییر a تاثیر مستقیم در n دارد. در نتیجه مقدار n در تابع قابل تغییر است. این برنامه هم مثل برنامه قبلی خروجی 5 دارد. در واقع متغیر مرجع همان کار اشارهگر را به صورت سادهتر انجام میدهد. چرا که برای متغیرهای مرجع نیاز به کار کردن با اپراتورهایی مانند & و * نیست.
پارامترهای مرجع کاربرد جالب دیگری نیز دارند. فرض کنید یک کلاس با صدها تابع و متغیر عضو تعریف کردهاید و تابعی دارید که یک متغیر از این نوع کلاس را دریافت کرده و بر اساس این دادهها، عملیاتی را انجام میدهد. به عنوان مثال:
با توجه به اینکه کلاس تعریف شده حجم زیادی دارد، انتقال اطلاعات بین برنامه و تابع به کندی انجام میشود. مخصوصا اگر مجبور باشید تابع را چندین و چند بار فراخوانی کنید (نظیر توابع مربوط به سربارگذاری عملگرها). در این حالت بهتر است تعریف فوق را با تعریف زیر عوض کنید:
void func(const myclass &a)
این عبارت متغیر a را به عنوان مرجع پارامتر متناظرش تعریف و انتقال اطلاعات از برنامه به تابع را لغو میکند. به عبارت سادهتر، با این تعریف، متغیر کلاس - با حجم بزرگ - از برنامه به تابع منتقل نشده و فقط a به عنوان مرجع (یا نام مستعار) برای پارامتر متناظرش شناخته میشود. به همین خاطر از عبارت const استفاده میکنیم، تا از تغییرات ناخواسته پارامتر تابع جلوگیری کنیم.
حرفهایترین کاربرد متغیرهای مرجع مربوط به انتقال اطلاعات از تابع به برنامه است. شما میتوانید یک متغیر مرجع را از تابع برگردانید. اما باید توجه داشته باشید که این مرجع مربوط به متغیر محلی تابع نباشد. چرا که با خروج از تابع متغیرهای محلی از بین میروند و در نتیجه مرجع آنها بیمعنی میشود. در واقع بیشتر مواقع از این روش در کلاسها و برای متغیرهای عضو کلاس استفاده میشود.
همانطور که قبلا عنوان کردم، مرجع یک متغیر با خود متغیر هیچ تفاوتی ندارد. این مسئله باعث میشود که شما بتوانید از توابعی با مقدار بازگشتی مرجع در سمت چپ علامت تساوی (=) استفاده کنید! برنامه زیر را در نظر بگیرید:
int arr[3];
int &func(int i) {
return arr[i];
}
void main() {
func(0) = 2;
func(1) = 6;
func(2) = -2;
cout << arr[0] << "\t" << arr[1] << "\t" << arr[2];
}
زمانی که تابع func با مقدار صفر فراخوانی میشود، یک مرجع به عنصر اول آرایه بر میگرداند. در نتیجه دستور اول تابع اصلی، مقدار این عنصر را برابر 2 قرار میدهد. خروجی برنامه به این صورت خواهد بود:
این خاصیت متغیرهای مرجع، قدرت زبان ++C را بسیار بالا میبرد. بزرگترین خدمت این روش به برنامهنویسان حرفهای ++C، زمانی است که برنامهنویس قصد دارد سربارگذاری عملگرها (Operator Overloading) را انجام دهد.
هنگام استفاده از متغیرهای مرجع به این نکات توجه کنید:
1 - متغیرهای مرجع در C وجود ندارد و مختص زبان ++C است.
2 - مرجع به متغیر مرجع نمیتوان تعریف کرد. قطعه کد زیر کامپایل نمیشود:
int a, &b = a;
int &c = b;
3 - آرایهای از مرجعها قابل تعریف نیست.
4 - از مرجعها برای ساختمانهای بیتی نمیتوان استفاده کرد.
5 - اشارهگر به مرجع وجود ندارد.