pointer یا اشاره گر متغیری هست که آدرس یک متغیر دیگه داخلش ذخیره میشه .
اگر توی برنامتون یک شی داشته باشین که قابل دسترسی باشه آدرس اون شی هم اغلب اوقات قابل دسترسیه .
اگر a یک شی باشه &a آدرس اون شی هست .
کاری که عملگر * میکنه برعکس & هست * به ما مقدار موجود داخل اشاره گر رو میده ولی & آدرس متغیر رو .
به & address operator و به * derefrence operator می گن .
مثال از نحوه تعریف اشاره گر :
int* x;
//ya
int *x;
2 تا عبارت بالا رو به ترتیب میشه به این شکل تفسیر کرد.
۱ـ x یک متغیره که از نوع *int ( اشاره گر به int ) هستش .
۲ـ x* از نوع int هستش (یعنی x آدرسیه که مقدار داخلش از نوع int هستش )
که هر ۲ تا تعریف بالا درست هستن و معادل همدیگه هستن .
مثال زیر رو در نظر بگیرید :
#include <iostream>
using namespace std;
int main()
{
int x=1;
cout<<x<<'\n';
int* p = &x;
*p = 2;
cout<< x ;
}
//khorooji :
//1
//2
توی کد بالا همون طوری که مشخصه با عوض کردن مقدار p مقدار داخل x هم عوض میشه چون x و p هر 2 به یک محل از حافظه اشاره می کنن پس عوض کردن هر کدوم باعث میشه که دیگری هم عوض بشه .
توی مثال بلا از اون جایی که int* p هم یک متغیره ما میتونیم به آدرسش دسترسی داشته باشیم به این شکل
int x = p;
int *p = &x
int **p2 = &p;
داخل کد بالا ما آدرس داخل p رو میزاریم داخل p2 .
این جا هم int **p2 رو میشه به این اشکال نوشت
int* *p2;
int **p2;
int** p2;
عبارات بالا رو هم به همون روشی که بالا گفتم میشه به ترتیب به این شکل تفسیر کرد :
1_ p2* (مقدار داخل p2 ) از نوع اشاره گر به int هستش ( *int )
2_**p2 ( مقدار داخل مقدار p2 ) از نوع int هستش .
3_ p2 از نوع اشاره گر به **int هستش ( اشاره گر به *int یا اشاره گری که به اشاره گر به int اشاره می کنه )
که هر 3 تعریف بالا معادل هم هستن .
به همین ترتیب میشه *** و **** و ... رو هم تعریف کرد .
حالا فرض کنید که این عبارت رو دارید :
int *x;
این جا x رو تعریف کردین ولی مقدار اولیه ندادین برای همین به حافظه نامشخصی اشاره می کنه .
برای مقدار اولیه دادن به اشاره گر از NULL یا nullptr استفاده می کنن
دلیل این کار هم اینه که با این کار شما در ادامه برنامه می تونید چک کنید که آیا x به حافظه خاصی اشاره می کنه یا نه .
int *x = nullptr ;
if(x==nullptr)
//..
else
//...
'گرفتن حافظه برای متغیر :
برای گرفتن حافظه برای متغیر در ++C از new استفاده می کنن
کاری که عبارت new T می کنه اینه که به اندازه متغیر T برای ما حافظه میگیره و یک اشاره گر به T ( که همون *T هست ) بر می گردونه .
برای مثال :
int *a = new int ; //gereftan hafeze baraye a
int *a= new int(5); //tafavotesh ba code bala ine ke inja *a meghdar avalie 5 migire
زمانی که از new استفاده می کنین حتما باید بعد از استفاده حافظه گرفته شده رو با استفاده از delete پاک کنید :
delete a;
برای گرفتن حافظه برای آرایه باید از new T[]l استفاده کنین
مثلا :
int *a = new int[10];
کد بالا به اندازه یک آرایه 10 عضوی برای ما حافظه می گیره و یک اشاره گر به خونه اول آرایه بر می گردونه که ما اونو داخل a میزاریم .
برای پاک کردن حافظه آرایه گرفته شده بوسیله new باید از delete[] استفاده بشه .
delete[] a;
نکته : دقت داشته باشین که استفاده از delete[] , delete به جای هم مشکل سازه و undefined behavior هستش (یعنی برنامتون ممکنه هر اتفاقی توش بیفته مثلا اگر از delete [] به جای delete استفاده کنین برنامه احتمال داره قسمت های حیاتی از حافظه رو پاک کنه که خطرناکه )
برای ساختن آرایه 2 بعدی هم باید به این شکل عمل کنین :
int **arr;
arr = new int*[5];
for(int i=0;i<5;i++)
{
arr[i]=new int[3];
}
کاری که کد بالا می کنه اینه که اول یک آرایه 5 تایی از *int با استفاده از new میسازیم که این جا new یک اشاره گر به خونه اول این آرایه بر میگردونه و از اون جایی که خونه اول از نوع *int هست پس آدرس *int که به شکل **int برگشت داده میشه و داخل arr گذاشته میشه .
بعد در مرجله بعد بوسیله حلقه for داخل هر خونه از این آرایه یک آرایه یک بعدی با اندازه 3 قرار میگیره .
برای پاک کردن آرایه 2 بعدی بالا هم به این شکل عمل کنید :
for(int i=0;i<5;i++)
{
delete[] arr[i];
}
delete[] arr;
واینکه مثلا کجا یک چیز new میشه ..مثلا point** چیه.
بر اساس توضیحات بالا **point یک اشاره گر به یک اشاره گر به point هستش
که خود این اشاره گر به point ممکنه
1_ به یک point اشاره کنه .
2_به خونه اول یک آرایه از point ها اشاره کنه .
یعنی بسته به این که کد چی باشه و **point رو به چه شکل بهش مقدار داده باشیم ممکنه یک آرایه 2 بعدی از point ها باشه یا این که ممکنه یک اشاره گر به آدرس یک point باشه .
نکته مهم : توی برنامه نویسی با ++C باید سعی بشه تا حد امکان از new استفاده نشه
برای استفاده از آرایه که سایزش زمان اجرا عوض میشه میتونین از vector استفاده کنین. به جای char* از string ,...
جاهایی هم که از new استفاده می کنین بهتره که از اشاره گر های هوشمند استفاده بشه تا حافظه گرفته شده به صورت خودکار پاک بشه .