Студопедия КАТЕГОРИИ: АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
Понятие ссылка (неявный указатель) ⇐ ПредыдущаяСтр 5 из 5
В чистом виде ссылка практически не используется. Основная ее область применения -формальные параметры и результат функции. Основные свойства ссылки -синтаксис обычной переменной в операциях с ней и реализация в виде неявного указателя -сохраняются. Инициализация же заменяется назначением неявной ссылки на фактический параметр или на переменную, сохраняющую результат.
void INC(int &a) void INC(int *pa) //---------------------------------------------------------- // Си++ Эквивалент в "классическом Си" //---------------------------------------------------------- { { a++; (*pa)++; } } ... ... int b = 5; int b = 5; INC(b); INC(&b);
При изменении значения формального параметра - ссылки происходит аналогичное изменение фактического параметра. Такой способ передачи параметров в языках программирования так и называется -ПЕРЕДАЧА ПАРАМЕТРА ПО ССЫЛКЕ. Несколько сложнее обстоит дело со ссылкой -результатом функции: -результат функции в операторе return и результат функции в выражении имеют синтаксис (тип) переменной; -в качестве результата возвращается неявный указатель, назначенный на переменную (адресное выражение), стоящее в операторе return; -если в выражении, содержащем вызов функции, производится преобразование результата в указатель на него (например, результат является фактическим параметром - ссылкой в следующем вызове), то неявный указатель передается без изменения в качестве операнда следующей операции; -если же используется сам результат (например, сохраняется путем присваивания), то производится косвенное обращение по неявному указателю.
int ©(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 = ©(&b); pc = COPY(&b); pc = ©(©(&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; просмотров: 163. stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда... |