Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курс лекцій.doc
Скачиваний:
15
Добавлен:
03.11.2018
Размер:
1.12 Mб
Скачать

1.7 Посилання та вказівники.

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

type &variablename=initexspression;

Тут variablename - це ідентифікатор змінної-посилання, що визначається, initexspression - це об’єкт, що має адресу в пам’яті(інколи використовується поняття L-вираз ). L-вираз (Lvalue-expression) - це вираз, що посилається на комірку пам’яті і тому має зміст в лівій частині бінарної операції присвоювання. Найпростіший приклад L-виразу є ідентифікатор вже визначеної змінної. Він посилається на комірку пам’яті, де зберігається значення цієї змінної. Посилання variablename визначає мiсце знаходження в пам'ятi iн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 фактично визначає 2 ідентифікатора, що пов’язуються з однією і тою ж коміркою пам’яті. При зміні значення одного ідентифікатора змінюється значення і другого. Змінна x обробляється компілятором як звичайна змінна типу int. При звертанні до такої змінної немає потреби в операції зняття посилання чи яких-небуть інших дій. Очевидно, що описаний вище фрагмент програми можна було б переписати з використанням вказівників:

int y=16;

int *x=&y;

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

y=12;

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

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

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

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

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

Розглянемо приклад:

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 - це рiзнi сигнатури . Тому , з врахуванням можливості перевантаження функцій, вони можуть бути записані в одній області видимості. Проте , в прикладі викликатись буде спочатку перша функція ( в рядку increment (v);). Адже фактичним параметром її повинне бути посилання. Потім викликається друга , параметром якої є вказівник. Друга функція викличеться, очевидно, і в такій ситуації:

int *v1;

*v1=6;

increment (v1);

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

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 в функції main() пояснюється елементарно. При виклиці функції changev(x+y) створюється локальна копія формального параметра , з якою працює функція (параметри передаються по значенню). В третьому випадку компілятор не може зв’язати посилання на тип int з змінною типу float. Тоді створюється тимчасова змінна, яка і зв’язується з р:

float r=-1.5;

int temp=r;

changev (temp);

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

int ivar=12;

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

int anotherint;

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

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

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

Приклад:

#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";

cin.getline (buffer,buflen)

done=(strlen(buffer)= =0);

if (!done){

index=ataf(buffer); // перетворення рядка в число

cout<<"введiть значення типу float";

cin.getline (buffer,buflen); /*введення значення в буфер*/

ref (index)=ataf (buffer);

}

}

return 0;

}

double & ref (int index)

{if (index<0) index=0;

return array [index];}

void showarray (void)

{cont <<"\n array:\n";

for (int i=0;i< SIZE;i++)

cout <<"["<<i<<"]"<<array[i]<<'\n';}