مراجع (References)
برای هر متغیر میتوان نام های دیگری تعریف کرد که استفاده از آنها مانند استفاده از خود نام متغیر اصلی است. پس ما یک متغیر داریم با چندین نام نه اینکه برای هر نام یک متغیر و فضایی از حافظه تخصیص داده شود. مثلاً برای تعریف مرجع numa برای متغیر num از نوع int که قبلاً تعریف شده است مینویسم:

;int &numa = num

ظاهر این تعریف مانند تعریف یک متغیر است با این تفاوت که قبل از نام مرجع یک & می آید. مرجع باید هم نوع متغیری باشد که به آن ارجاع میدهد. پس از این دستور در هرجای برنامه که از num استفاده میکردیم میتوانیم از numa بجای آن استفاده کنیم. یعنی مثلاً اگر از numa یکی کم کنیم دراصل از num یکی کم کرده ایم(نام متغیر و مراجع آن همگی نامی هستند برای یک قسمت از حافظه بنابراین هرکدام که تغییر کند همان قسمت مشترک تغییر خواهد کرد). ممکن است بپرسید که به چه دردی میخورد؟ یکی از کاربردهای آن در توابع مطرح میشود که بعداً خواهیم دید. البته از مرجع در صورت نیاز یا برای سرعت بخشیدن به برنامه(در توابع) استفاده میشود، بنابراین استفاده از آن زیاد نیست.

نکته: میتوان بیش از یک مرجع برای یک متغیر تعریف کرد.

توجه: نمیتوان بعداً تعیین کرد که یک مرجع به متغیر دیگری ارجاع دهد، پس یک مرجع همیشه به یک متغیر ارجاع میدهد.

توجه: مراجع در هنگام تعریف باید با نام متغیری که میخواهند به آن ارجاع دهند مقدار بگیرند، مثلاً قبلاً numa با num مقدار گرفت.
پس دستور ;int &numa خطا تولید میکند، چون به numa مقدار نمیدهد.

نکته: اگر یک مرجع به مرجع دیگری ارجاع دهد(با نام آن مقدار اولیه گیرد) در اصل بازهم به متغیر اصلی ارجاع میدهد و با اینکه با نام متغیر اصلی مقدار اولیه بگیرد فرقی نمیکند.

استفاده از const
اگر بخواهیم یک مرجع نتواند مقدار متغیری که به آن ارجاع میدهد را تغییر بدهد، از کلمه کلیدی const استفاده میکنیم: const int& numa = num مشخص میکند که numa به num ارجاع میدهد اما نمیتواند مقدار آنرا تغییر دهد، بنابراین دستوری مانند numa = 2 خطا تولید میکند.

نکته و توجه! : در تعریف هر متغیری که از const استفاده کنیم فقط همان متغیر غیر قابل تغییر خواهد بود، مثلاً وقتی یک ارجاع ثابت داریم فقط از طریق آن ارجاع نمیتوان مقدار متغیر اصلی را تغییر داد وگرنه از طریق نام متغیر غیر ثابت یا ارجاع های غیر ثابت دیگر به آن میتوان مقدارش را تغییر داد. پس هرجا که از const استفاده میشود فقط در مورد متغیری که در تعریف آن آورده شده یک محدودیت ثابت بودن میگذارد وگرنه به جای دیگری کاری ندارد!

توجه: برای یک متغیر ثابت باید یک ارجاع ثابت تعریف کرد وگرنه خطا دریافت میکنید چراکه اصل فضای حافظه که با متغیر اصلی گرفته میشود خاصیت ثابت بودن دارد و مرجعی که بعداً به آن حافظه رجوع میکند هم باید این محدودیت را داشته باشد تا حافظه را تغییر ندهد.


اشاره گرها(Pointers)
اشاره گر مانند یک مرجع عمل میکند و میتوان از آن برای دستکاری یک متغیر استفاده کرد اما چند تفاوت دارد:









خوب حالا تعریف یک متغیر اشاره گر: ;int* numa = &num ، متغیر numa به num اشاره خواهد کرد یعنی آدرس num در numa قرار میگیرد. استفاده از * تعریف یک اشاره گر را مشخص میکند. متغیر numa در اصل یک int به اندازه 4 بایت است(32 بیت)، پس اگر آنرا چاپ کنید 8 عدد hex مشاهده خواهید کرد که آدرسی از حافظه است(هر رقم hex بیانگر 4 بیت است، بنابراین 8 تای آنها 32 بیت را نشان میدهد). اشاره گر باید همنوع با متغیری باشد که به آن اشاره میکند، مگر اشاره گری از نوع void که میتواند به هر متغیری اشاره کند اما بعداً برای استفاده از مقدار متغیری که به آن اشاره میکند باید *void به یک نوع اشاره گر دیگر تبدیل شود(مثلاً *int تا بتوان عدد موجود در یک متغیر صحیح را نشان داد). البته *void موقعی استفاده دارد که نوع متغیری که به آن اشاره میکنیم را نمیدانیم و بعداً مشخص خواهد شد. بهرحال استفاده از *void موردی است.

نکته: مرجعی از نوع void نداریم، یعنی &void نادرست است.

نکته: برای تعریف چندین اشاره گر از یک نوع در یک دستور، مثلاً برای تعریف اشاره گرهای num1 و num2 از نوع int بنویسید: int *num1, *num2 ، یعنی * را برای هردو بیاورید وگرنه int *num1, num2 متغیر num1 را از نوع اشاره گر و num2 را از نوع متغیر صحیح تعریف میکند.

1. خود اشاره گر یک متغیر جداست که مقدار آن برابر آدرس متغیری قرار میگیرد که میخواهیم به آن اشاره کند. 2. میتوان تعیین کرد که یک اشاره گر به متغیر دیگری اشاره کند، یعنی لازم نیست همیشه به یک متغیر اشاره کند. 3. چون مراجع مکانی از حافظه را اشغال نمیکنند بنابراین برای صرفه جویی در حافظه مناسب هستند. 4. جایی هست که از مرجع نمیتوان استفاده کرد و باید از اشاره گر استفاده کرد. عملگر &
قبلاً از & برای تعریف یک مرجع استفاده کردیم، حالا استفاده دیگری از آن میکنیم که برگرداندن آدرس عملوند خود هست.
بنابراین در دستور ;int* numa = &num ابتدا num& آدرس num را برمیگرداند سپس مقدار numa برابر آن قرار میگیرد.

یک اشاره گر را میتوان ابتدا بدون مقداردهی اولیه تعریف کرد و بعداً مقدار آنرا مشخص کرد. پس میتوان ابتدا int* numa را داشت و بعداً numa = &num را نوشت تا numa به num اشاره کند. بعداً هر آدرس دیگری را هم میتوان در اشاره گر ریخت تا به آن اشاره کند.

عملگر *
تا اینجا با اشاره گر و نحوه اشاره به یک مکان از حافظه(یک متغیر) آشنا شدیم، اما اشاره گرها چه استفاده ای دارند؟ خود آدرس درون یک اشاره گر ممکن است مورد استفاده قرار گیرد اما معمولاً از قابلیت دسترسی اشاره گر به متغیری که به آن اشاره میکند استفاده میشود. در اینجا عملگر * استفاده میشود. این عملگر بر روی اشاره گرها اعمال میشود و متغیری که به آن اشاره شده را برمیگرداند(البته نه مقدار آنرا بلکه انگار شما خود متغیر را به جای اشاره گر استفاده کرده اید). مثلاً فرض کنید 23=int num و int* numa = &num را داریم، پس numa به num اشاره میکند. حالا میخواهیم به num از طریق numa دسترسی پیدا کنیم. مثلاً برای چاپ مقدار آن: cout << *numa مقدار 23 را چاپ میکند، پس فرض کنید که بجای numa* خود num قرار گیرد، ساده میشود نه؟! برای تغییر مقدار num هم: numa = 32* مقدار num را به 32 تغییر میدهد. البته در عبارات پیچیده تر به تقدم عملگرها هم توجه کنید و برای کاهش پیچیدگی، از پرانتزها استفاده کنید.
پس هروقت به خود متغیر اشاره شده نیاز داشتید از * بهمراه نام اشاره گر استفاده کنید و هر وقت به آدرس آن نیاز داشتید فقط از نام اشاره گر استفاده کنید.

استفاده از const
قبلاً از const برای مشخص کردن ثابت بودن مقدار یک متغیر استفاده کردیم، برای یک اشاره گر نیز میتوان دو جنبه از ثابت بودن را درنظر گرفت، یکی مقدار خود اشاره گر و دیگری مقدار متغیری که به آن اشاره میکند. مقدار اشاره گر که همان آدرسی است که به آن اشاره میکند اگر ثابت فرض شود پس باید هنگام تعریف اشاره گر مقدار بگیرد، یعنی int* const numa = &num که مشخص میکند numa به num اشاره میکند و بطور ثابت باید به همین جا اشاره کند و اگر بعداً آدرس دیگری در numa بریزید خطا تولید میشود، البته میتوان مقدار جایی که numa به آن اشاره میکند(num) را با استفاده از numa تغییر داد. اما برای ثابت فرض کردن جایی که اشاره گر به آن اشاره میکند باید const را قبل از * قراردهید(یا قبل از int ، که فرقی نمیکند) مثلاً const int* numa = &num مشخص میکند که با استفاده از numa نمیتوان مقدار num را تغییر داد(اما numa میتواند به هرجای دیگری اشاره کند). پس const int* const numa = &num مشخص میکند که numa نمیتواند بجای دیگری جز num اشاره کند و همچنین نمیتوان مقدار num را با استفاده از numa تغییر داد.

توجه: اگر یک متغیر ثابت دارید و میخواهید اشاره گری به آن تعریف کنید، باید در تعریف اشاره گرمشخص کنید که به یک متغیر ثابت اشاره میکند(یعنی const قبل از int را حتماً قرار دهید).