2.1. Присваивание структур

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

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

структуру с именем p, то результатом операции *p является структура в целом. Таким образом, структура приближается к базовым типам данных в том смысле, что над ней возможны вышеуказанные операции. Для обозначения структуры можно также использовать имя

структуры без ключевого слова struct.


struct dat

{ int day,month,year; }


dat NextDat(dat x) // Формальный параметр - структура

{ ... return(x); } // Возвратить структуру как результат


dat Nextdat1(dat *p)

{ ... return(*p); } // Возврат структуры косвенно по ссылке


dat a,b,c,*q; // Ключевое слово struct не используется

void main()

{

q = &b;

a = b; // Прямое присваивание структур

a = *q; // Косвенное присваивание по ссылке

c = NextDat(b); // Присваивание структуры как результата

c = NextDat1(&b); // функции, фактический параметр в

} // NextDat - копия структуры


2.2. Обращения по адресу (неявная ссылка)

----------------------------------------

При работе со структурами большого размера - при передаче их

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


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

------------------------ -----------------------------//--------------- Инициализация константой -----------------int &a = 5; int a, *pa =a;

*pa = 5;

//--------------- Инициализация переменной -----------------int x; int x,*pa;

int &a = x; pa = &x;


a = 5; *pa = 5;

//-------------- Неявная ссылка на структуру ----------------struct dat struct dat

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

dat x; dat x;

dat& b = x; dat* pb = &x;

dat& c = {12,12,1990}; dat cc = {12,12,1990};

dat *pc = &cc;


b.year = 1990; pb->year= 1990;

c.day=b.day+3; pc->day = pb->day+3;

c = b; // Копирование pc->day = pb->day;

// структуры pc->month = pb->month;

pc->year = pb->year;


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

параметрами - обычными значениями и неявными ссылками - синтаксически идентичен. То же самое касается результатов.


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

- значением;

- явной ссылкой;

- неявной ссылкой.


Пример 1. Параметры - значения

---------------------------------------------------------dat Inc(dat x) ========> - копирование

{ --------> - ссылка

x.day++;

return(x); ----¬ стек +---+x.day++

} ¦ b =========> x =========¬

L---- +---+ ¦ return(x)

void main() ¦

{ ----¬ стек +---+ --¦-¬ временная

dat a,b,*p; ¦ a day++

x->day++; ----¬ стек +---+

return(x); г===== b ¦

a = *Inc(Inc(&b)); ¦ ¦ L---- +-¦-+

p = Inc(&b); ¦ ¦ ----¬ ¦return(x)

a = *p; ¦ L-- a ¦

L---

Пример 3. Параметры - неявные ссылки

---------------------------------------------------------dat& Inc(dat& x) x.day++ неявная ссылка dat* px

{ x.day++

x.day++; ----¬ стек +---+

return(x); г===== b ¦

a = Inc(Inc(b)); ¦ ¦ L---- +-¦-+

p = &Inc(b); ¦ ¦ ----¬ ¦return(px)

a = *p; ¦ L-- a ¦

L---

Сравнение этих примеров показывает следующее:

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

- при возвращении результата используется имя переменной,которая заменяется транслятором неявной ссылкой на нее;

- примеры 2 и 3 идентичны по реализации, но отличаются по синтаксису вызова функции;

- примеры 1 и 3 отличаются по реализации, но идентичны по синтаксису вызова функции;

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


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

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

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

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

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


Программа на Си++ Реализация

----------------- ---------- -- неявный параметр

dat Inc(dat x) void Inc(dat *r,dat x)

{ {

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

return(x); *r = x; // Копирование

} } // результата


void main() void main()

{ {

dat a,b*p; dat a,b,*p;

dat t,u; // Временнye переменнye

a = Inc(b); Inc(&a,b); // Ссылка на левую часть

p = &Inc(b); Inc(&t,b); // Присаивание временной

p = &t; // переменной и получение

a = *p; a = *p; // ссылки на нее

a = Inc(Inc(b)); Inc(&u,b); // Промежуточный результат

Inc(&a,u); // во временной переменной

} }



Информация о работе «Объективное программирование»
Раздел: Информатика, программирование
Количество знаков с пробелами: 61028
Количество таблиц: 0
Количество изображений: 0

Похожие работы

Скачать
14044
1
2

... обучающих программ Обучающие программы, построенные на бихевиористской основе, подразделяют на: а) линейные, разработанные Скиннером, б) разветвленные программы Н. Краудера. 1. Линейная система программированного обучения, первоначально разработанная американским психологом Б. Скиннером в начале 60-х гг. ХХ в. на основе бихевиористского направления в психологии. ·  Он выдвинул следующие ...

Скачать
93027
12
0

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

Скачать
109055
0
0

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

Скачать
165676
21
12

... отбора. ГЛАВА II. ЦЕЛЬ, ЗАДАЧИ, МЕТОДЫ И ОРГАНИЗАЦИЯ ИССЛЕДОВАНИЯ   2.1 Цель и задачи исследования Цель исследования - повышение эффективности физической подготовки вратарей учебно-тренировочных групп на соревновательном этапе. В процессе реализации поставленной цели решались следующие основные задачи: 1.     Изучить особенности возрастного развития двигательных способностей футболистов ...

0 комментариев


Наверх