Операція адресації буде посиланням, якщо вона вжита у контексті:
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";