Печать
Категория: C++
Просмотров: 1579

Ишораҳо (pointers, ишоракунакҳо) дар назари аввал муҷмаланд ва боз савол оиди зарурияти донистани онҳо пайдо шуданаш мумкин аст. Ҳақиқат дар он аст, ки онҳо метавонанд бисёр чизҳоро осонтару соддатар кунанд. Масалан, ба воситаи ишоракунакҳо шумо метавонед дар дохили функсия қимати тағйирёбандаеро, ки ба функсия ҳамчун аргумент нақл мешавад, тағйир диҳед; инчунин, дар рафти кори барнома метавонед барои массивҳо ё рӯйхатҳои пайваста ҳаҷми зарурии хотираро ҷудо намоед ва онро боз озод намоед.

Вазифаи ишоракунакҳо аз номи онхо маълум мегардад, яъне онҳо ба ягон қисми хотираи фаврӣ ишора мекунанд. Тасаввур кунед, ки як хонае мавҷуд аст, ки дар он пиёлаҳои бисёре гузошта шудаанд. Дар яке аз ин пиёлаҳо порчаи қоғазе гузошта шудааст. Дар ин қоғаз мавқеи пиёлаи дигар навишта шудааст. Шумо ба он мавқеъ мегузаред ва он пиёлаи дигарро мегиред. Дар ин пиёлаи дуюм боз порчаи қоғазе ҳаст, ки дар он 18 навишта шудааст. Инак, пиёлае, ки дар он 18 буд, тағйирёбанда аст ва пиёлае, ки дар он мавқеи ин 18 навишта шуда буд, ишоракунак ба 18 аст.

Тарзи кор бо ишоракунакҳо низ аҷоиб аст, чунки ба воситаи онҳо мавқееро дар хотира аниқ намудан мумкин аст ва ё метавон қиматеро, ки дар он мавқеъ нигоҳ дошта мешавад, дастрас намуд. Албатта, пеш аз истифодаи ишоракунак онро эълон кардан зарур аст ва қоидаи эълоннамоӣ чунин аст:

variable_type *name; 

Дар ин ҷо variable_type - намуде, ки ба он ишоракунак name ишора карда метавонад. Ба рамзи ситорача (*) аҳамият дихед, мавҷуд будани он пеш аз номи ягон тағйирёбанда нишони он аст, ки ин тағйирёбанда ишоракунак аст. Масалан:

int *p; float *d15; 

Дар ин ҷо p ишора ба ягон адади бутун ва d15 ишора ба ягон адади ҳақиқӣ мебошанд.

Гуфтан зарур аст, ки ду роҳи истифодаи ишоракунак барои дастрас намудани маълумот оиди хотирае, ки ба он ишоракунак ишора мекунад, мавҷуд аст. 1) Мумкин аст, ки мавқеи ягон тағйирёбандаи дигарро дар хотира муайян намоем ва ё 2) мавқеи ягон тағйирёбандаро ба ягон функсия нақл намоем. Барои ин, танҳо номи ишоракунакро истифода бурдан кифоя аст (бе рамзи *).

Лекин барои дастрас намудани қимате, ки дар ин мавқеъ (адрес) ҷойгир аст, рамзи ситорачаро (*) истифода бурдан зарур аст. Номи техникии ин амал dereferencing мебошад.

Барои он ки ишоракунак ба ягон тағйирёбанда воқеан ишора кунад, зарур аст, ки адреси ин тағйирёбанда дар хотираро донем. Барои муайян кардани адреси тағйирёбанда дар хотира рамзи амперсандро (&) пеш аз номи тағйирёбанда гузоштан зарур аст. Азбаски ин амал адреси тағйирёбандаро бозмегардонад, он оператори ишора номида мешавад.

Мисол:

//namuna16.cpp
using namespace std;
#include <iostream>
int main() {
int x;
int *p;
p=&x;
cout<<"Kimati x:";
cin>>x;
cout<<"Kimati x "<<*p<<" ast."<<endl;
cout<<"Adresi x dar khotira "<<p<<" ast."<<endl;
return 0;
}

Дар int x; тағйирёбандаи оддии бутун эълон шудааст. Дар int *p; ишоракунак ба адади бутун эълон шудааст. Баъд, ба p бахшида шудааст адреси x дар хотираи фаври (RAM), ба воситаи рамзи &. Баъди аз тарафи истифодабаранда дохил карда шудани қимати x, cout қиматеро, ки дар мавқее бо адреси p ҷойгир аст, чоп мекунад. Яъне, * пеш аз номи ишоракунак p қимати дар мавқее, ки ба он ишоракунак p мебарад, сабтшударо медиҳад. Худи p бе рамзи ситорача адреси мавқеъро медиҳад. Қайд мекунем, ки ишоракунак ба мавқеи x пеш аз ба x бахшидани ягон қимат ишора мекунад. Яъне баъди эълони тағйирёбанда мавқеи он дар хотира муайян аст, гарчанде қимати тағйирёбанда муайян нест.

Пеш аз истифодаи ишоракунак ба он ягон адресро бахшидан зарур аст, дар ҳолати баръакс дар рафти иҷрои барнома хатогӣ ва кандашавии иҷрои барнома ба амал омаданашон мумкин аст.

Як мисоли дигар:

//namuna17.cpp
using namespace std;
#include <iostream>
int main() {
int y;
int *pr;
pr=&y;
y=7;
cout<<"Kimati y "<<*pr<<" ast."<<endl;
cout<<"Adresi y dar khotira "<<pr<<" ast."<<endl;
*pr=15;
cout<<"Kimati *pr "<<y<<" ast."<<endl;
cout<<"Kimati pr "<<&y<<" ast."<<endl;
return 0;
}

Дар мисолҳои болои ишораҳо ба мавқеъҳое, ки аллакай аз тарафи тағйирёбандаҳои дигар (x ва y) забт карда шудаанд, ишора мекарданд.

Дар ин ҷо бояд гуфт, ки тағйирёбандаҳои намудҳои гуногун андозаҳои гуногун доранд. Яъне тағйирёбандаҳо вобаста аз намудашон метавонанд миқдори гуногуни байтҳоро дар хотира банд намоянд. Барои муайян кардани ҳаҷми ин ё он намуд аз функсияи sizeof() истифода мебаранд. Мисол:

//namuna18.cpp
using namespace std;
#include <iostream>
int main() {
cout<<"Andozai namudi int - "<<sizeof(int)<<" byte ast."<<endl;
cout<<"Andozai namudi float - "<<sizeof(float)<<" byte ast."<<endl;
cout<<"Andozai namudi char - "<<sizeof(char)<<" byte ast."<<endl;
cout<<"Andozai namudi double - "<<sizeof(double)<<" byte ast."<<endl;
cout<<"Andozai namudi long - "<<sizeof(long)<<" byte ast."<<endl;
return 0;
}

Дар ин ҷо намуди long барои ададҳои бутуни калон лозим аст.

Имконпазир аст, ки ишоракунакҳо ба ягон мавқеи озоди хотира ишора кунанд. Ин имконият медиҳад, ки ҳаҷми зарурии хотираи фаврӣ дар рафти иҷрои барнома забт ва озод карда шавад. Чунин имконият барои сохтани массивҳои дарозиашон тағйирёбанда ё рӯйхатҳои пайваст лозим мешавад, ки дар мавзӯъҳои оянда бо онҳо шинос мешавем. Лекин тавонистани истифодаи калимаҳои махсуси delete ва new дар оянда лозим мешавад. Калимаи махсуси new барои ба ишоракунак бахшидани адреси ягон мавқеи озоду ба барнома дастраси хотираи фаврӣ истифода бурда мешавад. Тарзи истифодаи ин оператор чунин аст:

variable_type *ptr = new  variable_type; 

Дар ин сатр ду амал иҷро карда мешавад:
1) қисми озоди хотира, ки ҳаҷмаш ба андозаи намуди variable_type баробар аст, бо оператори new забт мешавад.
2) ишоракунак ptr ба ин қисми нав забтшудаи хотира ишора мекунад.

Ин қисми хотираро барномаҳои дигар истифода бурда наметавонанд. Аз ин ҷо хулоса мебарояд, ки бо хотира эҳтиёткорона рафтор намуда, қисми забтшударо, баъди гум шудани зарурият ба он, ҳатман озод намудан зарур аст. Оператори delete хотираи ба воситаи new забтшударо озод менамояд. Намуди истифодаи ин оператор чунин аст:

delete ptr; 

Дар ин ҷо ptr номи ишоракунак аст. Услуби хуби барномасозӣ талаб мекунад, ки баъди озод кардани хотираи забтшуда, ба ишоракунаки озодшуда NULL бахшем:

delete ptr; ptr = NULL; 

NULL ин доимиест, ки дар компилятор муайян буда, ишора ба NULL ин ишора ба "ҳеҷ" аст. Ин рафтор шуморо аз истифодаи хатои ишора эмин медорад. Боз як вазифаи NULL чунин аст: агар дар хотира дигар ҷои холӣ набошад, оператори new барои ишоракунак ягон қисми хотираро забт карда наметавонад ва ишоракунак ба NULL баробар аст. Аз ин сабаб, аз руи услуби хуби барномасозӣ санҷидан лозим аст, ки ишоракунак ба ягон ҷо ишора мекунад ё не. Мисол:

//namuna19.cpp
using namespace std;
#include <iostream>
int main() {
int *y;
y = new int;
if(y==NULL)
cout<<"Dar khotira joi kholi nest."<<endl;
return 0;
}

САВОЛҲО БАРОИ МУСТАҲКАМКУНӢ
1. Вазифаи ишоракунакро бо мисол фаҳмонед.
2. Вазифаи амалҳои * ва & чист?
3. Бо кадом мақсад ба ишоракунак қимати NULL мебахшанд?
4. Вазифаи операторҳои delete ва new чист?