Лекция 09 (лекции (2002)), страница 2

2019-09-19СтудИзба

Описание файла

Файл "Лекция 09" внутри архива находится в папке "лекции (2002)". Документ из архива "лекции (2002)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .

Онлайн просмотр документа "Лекция 09"

Текст 2 страницы из документа "Лекция 09"

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

Способы передачи параметров:

  1. По значению (реализует семантику in)

  2. По результату (реализует семантику out)

  3. По значению/результату (реализует семантику in out)

  4. По ссылке (адресу)

  5. По имени

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

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

При передаче параметра по адресу в локальной памяти выделяется место только под указатель.

В С единственный способ передачи параметров – по значению. Этот способ реализует только семантику in. В случае, если мы хотим реализовать семантику in out в языке С, мы должны сами реализовать передачу параметра по ссылке. Т.е., если мы хотим написать процедуру, меняющую значение своего аргумента, мы должны передавать вместо самого аргумента его адрес

void f(int *p)

и далее везде, где требуется значение аргумента надо явно разыменовывать указатель: *p.

Если в языке есть способ передачи по ссылке, значит, в языке есть возможность делать все это автоматически. Такой способ передачи есть в языке Паскаль и всех языках, которые на нем основаны. Если параметр описан

VAR X:T;

то вместо него передается соответствующий адрес. И везде, где встречается Х

X:= Y;

Y:= X;

он означает операцию разыменования соответствующего адреса.

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

Во всех, рассматриваемых нами ЯП, есть передача параметров по значению. Большинство компьютерных архитектур явным образом поддерживают механизм передачи параметров – в современных вычислительных архитектурах аппаратно реализован стек. Как следствие, передача параметров по значению есть везде.

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

В первых реализациях языка FORTRAN был единственный способ передачи параметров – по ссылке, т.к. он наиболее универсален. В конкретной реализации FORTRAN можно было изменить значение константы 1 следующим образом. Передаем константу 1 по ссылке как фактический параметр, меняем в процедуре значение этого параметра. Учитывая то, что большинство реализаций под константы отводит место в статической памяти, значение константы потеряно. Это свидетельствует о том, что механизм передачи информации, который не сопровождается защитой соответствующих параметров, крайне ненадежен. С другой стороны, организация передачи по ссылке явным образом, как это есть в языке С, тоже неудачное решение. Поэтому Страуструп ввел в С++ специальный ТД ссылка, одним из основных применений которого было введение в язык нового способа передачи параметров – по ссылке.

T & x

Т.е. в С++ так же как и в Паскале программист может выбирать соответствующий способ передачи параметра – либо по значению, либо по ссылке.

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

const T & x

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

В языке Ада 83 программист фиксирует только семантику для контроля компилятором. Т.е. если параметр in, то меняться он никак не может. Компилятор сам должен выбирать соответствующий способ реализации. В Аде 95 если параметр содержит массив, он всегда должен передаваться по ссылке, т.к. в языке Ада есть различие передается параметр по значению/результату или по ссылке. Оно проявляется в очень редких случаях. Например:

P(X, Y: in out T)

Если фактические параметры X и Y различны, то с точки зрения программиста никакой разницы нет передаются данные по значению/результату или по ссылке. Пусть в теле процедуры

X:= 1;

может случиться аварийная ситуация (деление на 0, …), возникает

исключение (exception) и управление покидает процедуру.

Y:= 2;

Пусть есть переменная

A: T;

Если мы вызываем

P(A, A);

Если процедура заканчивается нормально, А получит значение 2 вне зависимости от способа реализации передачи параметров. Если при вызове между двумя операторами присваивания возникает исключение, то значение А будет зависеть от способа передачи параметров. Если передача по значению/результату, то т.к. X и Y меняют значение, А должно поменять значение в момент нормального выхода из процедуры. В случае, если возникает исключение, копирования из формального параметра в фактический не произойдет, значение А останется прежним. Если мы передаем параметр по ссылке, любое изменение формального параметра тут же отражается на фактическом, следовательно, значение А станет равным 1. Самое неприятное то, что это различие сказывается при переносе программы с одного компилятора на другой, в которых приняты разные способы передачи параметров. Когда программа работает нормально, оба компилятора работают эквивалентно. Но, хоть и редко, могут возникать описанные выше ситуации. Следовательно, этим снижается мобильность программ. Поэтому создатели нового стандарта языка Ада постулировали: когда используется семантика in, способ передачи параметра выбирает компилятор. Для массивов и для записей, которые содержат большую информацию, он выбирает способ передачи по адресу. Для простых переменных он всегда выбирает способ передачи параметра по значению. Для всех in out режимов компилятор Ада 95 всегда выбирает способ передачи по ссылке вне зависимости от того, передаваемая переменная простого ТД или сложного составного. В результате улучшается переносимость программ с одного компилятора на другой.

Модула 2 и Оберон наследуют семантику Паскаля. Программист выбирает либо семантику in, либо семантику in out.

Delphi также наследует семантику Паскаля, но семантика классов в Delphi такая же как в Java и C#. В Java все ТД делятся на простые базисные ТД и ссылочные типы, к которым относятся массивы, классы и интерфейсы.

void f(int x) {…}

Способ передачи для всех простых ТД по значению. А имена всех составных ТД являются ссылками, поэтому они передаются по ссылке.

void f(String a) {…}

а передается по ссылке, поскольку String –имя стандартного класса.

В Delphi соответственно

procedure P (X: T)

Если Т – простой ТД, то Х передается по значению. Если Т – имя класса, значит Х – ссылка на объект класса Т. Следовательно Х передается по ссылке.

procedure P (VAR X: T)

Если Т – имя класса в языке Delphi, в этом случае передается ссылка на ссылку. И в том, и в другом случае мы имеем право модифицировать состояние фактического аргумента, поскольку нам доступна ссылка. Например:

X.Free

Передавать с помощью VAR надо, когда мы в процедура Р хотим Х присвоить какое-нибудь значение.

X:= T.Create

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

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

int - Int

char - Char

… … …

Здесь мы сталкиваемся с концепцией рефлексии. В Java есть специальный пакет Java.lang. Внешне он выглядит как обычный стандартный пакет языка Java. Отличие стандартной библиотеки от компилятора в том, что компилятор менять не рекомендуется, а стандартную библиотеку поменять можно. Можно написать свою реализацию библиотеки. Классы из пакета Java.lang внешне ничем не отличаются от классов из библиотеки. Но часть семантики всех этих классов зашита в компиляторе. В частности, классы обертки – классы из Java.lang. Опишем некоторую функцию, в качестве формального параметра которой будет указан не объект простого ТД, а объект класса-обертки.

void f (Int x) {x= 1;}

Т.к. это класс, то объект передается по ссылке.

int a;

f(a);

Компилятор не выдаст сообщение о несоответствии типов. В языке Java никакие неявные преобразования не разрешены, кроме преобразований для классов-оберток, которые входят в Java.lang. В данном случае компилятор произведет соответствующую обертку

f(Int(a));

Тем самым решена проблема моделирования любой семантики. Если мы хотим для простых ТД реализовывать семантику in out мы должны описывать соответствующий формальный параметр как объект не самого простого ТД, а соответствующего ТД обертки.

Ко многим свойствам ТД можно добраться не с помощью каких-то констант типа maxint, minint, …, а как к свойствам соответствующего класса обертки. Это верно для всех классов обертки.

В C#, как и в языке Java, классы имеют ссылочную семантику, в отличие от простых ТД. Кроме этого в С# есть структуры.

struct

Они отличаются от структур в С++. Внешне они выглядят как классы, но они значительно более ограничены. Они не могут наследоваться явно, а наследуются только неявно из ТД object. От них ничего не может наследоваться. У них не может быть конструкторов по умолчанию. Они не имеют ссылочной семантики. Если структура описана как локальная переменная, она размещается в стеке. (Для класса в стеке размещалась бы только ссылка.) Поэтому в С# появилось понятие Boxing. В случае, когда надо передавать структуру как формальный параметр, структура преобразуется в экземпляр некоторого класса, и передается ссылка на экземпляр этого класса. Т.е. Boxing – это преобразование из не ссылочной структуры в ссылочный класс.

Для простых ТД в языке есть два ключевых слова – ref и out. Ключевое слово ref означает способ передачи по ссылке.

void f(ref int a);

ref реализует семантику in out, т.е. от формального параметра требуется значение определенности и он может менять свое значение. В C# при появлении переменных всем ссылочным переменным присваивается нулевое значение, а всем переменным простого типа присваивается несуществующее значение. При попытке

i:= a;

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

int x;

f(x);

Свежие статьи
Популярно сейчас
А знаете ли Вы, что из года в год задания практически не меняются? Математика, преподаваемая в учебных заведениях, никак не менялась минимум 30 лет. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5301
Авторов
на СтудИзбе
417
Средний доход
с одного платного файла
Обучение Подробнее