Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Понятие ссылка (неявный указатель)




В чистом виде ссылка практически не используется. Основная ее область применения -формальные параметры и результат функции. Основные свойства ссылки -синтаксис обычной переменной в операциях с ней и реализация в виде неявного указателя -сохраняются. Инициализация же заменяется назначением неявной ссылки на фактический параметр или на переменную, сохраняющую результат.

 

void INC(int &a)  void INC(int *pa)

//----------------------------------------------------------

// Си++            Эквивалент в "классическом Си"

//----------------------------------------------------------

{                  {

a++;               (*pa)++;

}                  }

...                ...

int b = 5;            int b = 5;

INC(b);            INC(&b);

 

При изменении значения формального параметра - ссылки происходит аналогичное изменение фактического параметра. Такой способ передачи параметров в языках программирования так и называется -ПЕРЕДАЧА ПАРАМЕТРА ПО ССЫЛКЕ.

 Несколько сложнее обстоит дело со ссылкой -результатом функции:

 -результат функции в операторе return и результат функции в выражении имеют синтаксис (тип) переменной;

-в качестве результата возвращается неявный указатель, назначенный на переменную (адресное выражение), стоящее в операторе return;

-если в выражении, содержащем вызов функции, производится преобразование результата в указатель на него (например, результат является фактическим параметром - ссылкой в следующем вызове), то неявный указатель передается без изменения в качестве операнда следующей операции;

 -если же используется сам результат (например, сохраняется путем присваивания), то производится косвенное обращение по неявному указателю.

 

int &COPY(int *pa)     int  *COPY(int *pa)

//---------------------------------------------------------

// Си++                  Эквивалент в "классическом Си"

//---------------------------------------------------------

{ return(*pa);} {return(pa);}

int a,b = 5,*pc;         int a,b = 5,*pc;

//-- Косвенное обращение по неявному указателю - результату

a = COPY(&b);            a = *COPY(&b);

//-- Передача неявного указателя без изменения ------------

pc = &COPY(&b);          pc = COPY(&b);

pc = &COPY(&COPY(&b));pc = COPY(COPY(&b));

Обратите внимание, что тип результата в операторе return(*pa) -не указатель, а указуемый тип. То же самое и в выражении, где находится вызов функции COPY(&b), то есть по синтаксису функция COPY возвращает не тип-указатель, а тип указуемой переменной.

Заменив в формальном параметре указатель на ссылку, получим наиболее распространенный способ "прозрачной" передачи ссылки через функцию. Он позволяет организовать цепочку вызовов функций, передающих неявный указатель с выхода функции на вход следующей:

 

int &INC(int &a)       int *INC(int *pa)

//---------------------------------------------------------

Си++                     Эквивалент в "классическом Си"

//---------------------------------------------------------

{ a++;return(a); } { (*pa)++; return(pa);}

int а,b = 5;int а,b = 5;

а = INC( INC( INC(b))); a = *INC( INC( INC(&b)));

Не следует забывать, что результат-ссылка всегда является неявным указателем, и он не может указывать на переменные, недействительные после выхода из функции. Поэтому нельзя возвращать таким способом автоматические переменные и выражения, которые не являются адресными.

 Если рассматривать функцию как конвейер, передающий некоторую переменную со входа функции на выход, то имеется три способа такой передачи:

-значением; -обычным указателем; -ссылкой.

 

// 1. Параметр и результат - значения

//--------------------------------------------------------

struct dat { int day,month,year; };

                             //Эквивалент

dat Inc(dat x)         //void Inc(dat x, dat *pout)

{                       //{

x.day++;                //x.day++;

return x;               //*pout = x;}

}                       //

void main()          //

{                       //

dat a,b,*p;         //

a = Inc(Inc(b));         // dat tmp1; Inc(x=b,&tmp1);

p = &Inc(b);            // dat tmp2; Inc(x=tmp1; &tmp2);

a = *p;                // dat tmp3; Inc(Inc(x=b,&tmp3);

}                            // p = &tmp3; a = *p;

 

// 2.Параметр и результат - указатели

//-------------------------------------------------------

struct dat { int day,month,year; };

 

dat* Inc(dat* x)          //

{                         //

x->day++;                //        

return x;                 //                                                                     

}                        //   

void main()           //

{                        //                   

dat a,b,*p;          //     

a = *Inc(Inc(&b));          //

p = Inc(&b);             //     

a = *p;                  //     

}                        //     

 

// 3. Параметрирезультат - ссылки

//-------------------------------------------------------

struct dat { int day,month,year; };

 

dat& Inc(dat& x)          //Эквивалент

{                        // dat *Inc(dat *px)

x.day++;                 // { (*px).day++;

return x;                 // return px;}

}                        //

void main()           //

{                        //

dat a,b,*p;          //

a = Inc(Inc(b));          // dat *pp; pp=Inc(&b); a=*Inc(pp);

p = &Inc(b);             //p = Inc(&b);

a = *p;                  //a = *p;

}                        //     

Ссылка в качестве формального параметра используется всегда, когда требуется изменить значение соответствующего фактического параметра при вызове функции. Тип параметра может быть любым. В качестве примера рассмотрим ССЫЛКУ НА УКАЗАТЕЛЬ на текущий элемент списка и на текущую вершину двоичного дерева в операциях включения. В соответствии с принципом контекстного определения типа данных последовательность операций "&,*" читается от переменной p справа налево как ссылка на указатель.



Передача и возврат параметров по ссылке

//---------------------------------------------------- 1

double &F1(double s[], int n)

{ int i,k; double d;

for (i=1, k=0, d=s[0]; i<n; i++)

if (s[i] > d) { k=i; d=s[i]; }

return(s[k]);

}

//---------------------------------------------------- 2

void F2(char *&p, char *s)

{p = new char[strlen(s)+1];

strcpy(p,s);

}

//---------------------------------------------------- 3

struct tree

  { int val;

  tree *pr,*pl;

  };

void F3(tree *&p, int v)

{

if (p==NULL)

  { p = new tree;

  p->pl = p->pr=NULL;

  p->val = v; return;

  }

if (p->val = v) return;

if (p->val > v) F3(p->pl,v); else F3(p->pr,v);

}

//------------------------------------------------------

// Определить значения переменных после выполнения действий

//----------------------------------------------------- 4

int INC4(int &x)

  { x++; return(x+1); }

void main()

{ int x,y,z; x = 5; y = INC4(x); 

z = INC4(INC4(x)); }

//----------------------------------------------------- 5

int &INC5(int &x)

  { x++; return(x); }

void main()

{ int x,y,z;

x = 5; y = INC5(x); z = INC5(INC5(x)); }

//----------------------------------------------------- 6

int *INC6(int &x)

{ x++; return(&x); }

void main()

{ int x,y,z; x = 5; y = *INC6(x);

z = *INC6(*INC6(x)); }

//----------------------------------------------------- 7

int INC7(int x)

  { x++; return(x+1); }

void main()

{ int x,y,z; x = 5; y = INC7(x); 

z = INC7(INC7(x)); }

 

 










Последнее изменение этой страницы: 2018-05-10; просмотров: 162.

stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда...