Посилання й покажчики

Операція адресації буде посиланням, якщо вона вжита у контексті:

type &variablename=initexspression;

Тут variablename – ідентифікатор змінної-посилання, що визначається, initexspression – об'єкт, що має адресу в пам'яті (інколи використовується поняття L-вираз). L-вираз – це вираз, що посилається на комірку пам'яті й тому має зміст у лівій частині бінарної операції присвоювання. Найпростішим прикладом L-виразу є ідентифікатор уже визначеної змінної. Він посилається на комірку пам'яті, де зберігається значення цієї змінної. Посилання variablename визначає місцезнаходження в пам'яті iнiцiалiзуючого виразу.

Змінна-посилання має бути обов'язково iнiцiалiзована. Оголошення вигляду Type & varname; не допускаються. Розглянемо фрагмент програми:

int y=16;

int & x=y;

printf ("x=%d\n",x);

y=12;

printf ("x=%d\n",x);

Результат:

x=16

y=12

Оголошення int &x=y фактично визначає два ідентифікатори, що пов'язуються з однією й тією самою коміркою пам'яті. При зміні значення одного ідентифікатора змінюється значення й другого. Змінна x обробляється компілятором як звичайна змінна типу int. При звертанні до такої змінної немає потреби в операції зняття посилання чи яких-небудь інших діях. Описаний вище фрагмент програми можна переписати з використанням покажчиків:

int y=16;

int *x=&y;

printf("x=%d\n",*x);

y=12;

printf("x=%d\n",*x);

Бачимо, що посилання суттєво відрізняються від покажчиків.

Найчастіше посилання використовуються як формальні параметри функцій. Це робиться з двох основних причин:

а) для підтримки режиму зв'язку (аналог var у Pascal);

б) щоб не допустити копіювання змінних у стек.

Покажемо, як це зробити:

void increment(int& x)

{x+=1;}

void increment(int*x)

{*x=*x+1;}

Main()

{

int v=3;

increment(v);

int anotherv=5;

increment(& anotherv);

printf ("v=%d\n",v);

printf ("anotherv=%d\n",anotherv);}

Результат:

v=4

anotherv=6

Конструкції int& x та int* x – це різні сигнатури. Тому, з урахуванням можливості перевантаження функцій, їх можна записати в одній області видимості. Проте викликатиметься спочатку перша функція (у рядку increment (v);), адже фактичним параметром її має бути посилання. Потім викликається друга, параметром якої є покажчик. Друга функція викличеться й за такої ситуації:

int*v1;

*v1=6;

increment(v1);

Використання посилань як формальних параметрів функцій має деякі особливості. Розглянемо програму:

void changev(int&p)

{p+=20;

printf("значення p у функцiї=%d\n",p);}

Main()

{int x=50;

changev(x);

printf("x=%d\n",x);

int y=100;

changev(x+y);

printf("x=%d y=%d\n",x,y);

float r=-1.5;

changev(r);

printf("r=%0.2f\n",r);

}

Результат:

значення p у функцiї=70

x=70

значення p у функцiї=190

x=70 y=100

значення p у функцiї=19

r=-1.50

Результат виклику функції changev з аргументом x у функції main() пояснюється елементарно. При виклику changev(x+y) створюється локальна копія формального параметра, з якою вона працює (параметри передаються за значенням). У випадку виклику changev(r) компілятор не може зв'язати посилання на тип int зі змінною типу float. Тоді створюється тимчасова змінна, яка і зв'язується з р:

float r=-1.5;

int temp=r;

changev(temp);

Після iнiцiалiзації посилання йому не можна присвоїти інші значення:

int ivar=12;

int &iref=ivar; /*Посилання на ivar*/

int anotherint;

iref=anotherint; //не допускається

Посилання можуть повертатися функцiями: double & ref(int d);

Функції посилання використовуються для закриття внутрішнього зображення структури даних. Наприклад:

#define FALSE 0

# define SIZE 100

#define BUFLEN 100

double & ref(int index);

void showarray(void);

double array[SIZE];

Main()

{int done=FALSE,index;

char buffer[BUFLEN];

for(index=0;index<SIZE;index++)

ref(index)=index;

while(!done)

{showarray();

cout<<"\n введiть index вiд 0 до 9\n";


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: