Передача параметров по имени и по значению




Структура подпрограммы.

Описание подпрограммы состоит из трех частей: заголовка подпрограммы, локального описания и тела подпрограммы. Заголовок используется, чтобы явно ввести в программу новую подпрограмму и обозначить начало ее описания. Локальные описания представляют собой набор описаний типов, переменных, констант и других подпрограмм, которые действуют только в рамках данной подпрограммы. Тело подпрограммы - это логический блок begin/end, содержащий операторы и команды Паскаля и реализующий нужную логику работы.
ВНИМАНИЕ. Описание подпрограммы - это только описание, которое никогда не выполняется само по себе и может располагаться в любом месте исходного текста (но обязательно до первого вызова подпрограммы). Вызывается процедура или функция только внутри логического блока be-gin/end с указанием конкретных значений для каждого из ее параметров.
Заголовок
Заголовок подпрограммы состоит из трех частей: ключевого слова, ха-рактеризующего тип подпрограммы (процедура - procedure, или функция - function), списка параметров, перечисленных через точку с запятой и взятых в круглые скобки, и (только для функций) типа возвращаемого значения, указы-ваемого вслед за двоеточием.
Список параметров содержит параметры, каждый из которых представляет собой произвольное имя переменной и соответствующий ей тип через двоеточие. Если несколько параметров имеют одинаковый тип, то их можно перечислить через запятую.
procedure Compute(X: Integer; S: String);
function Compare(Al, A2: Byte; Stroka: String): Real;
procedure ShowMap;
function GameOver: Boolean;
Список параметров может быть опущен. Для некоторых параметров могут быть заданы значения по умолчанию (все параметры с такими значе-ниями должны располагаться вместе и после параметров, для которых не задано значений по умолчанию).
procedure МуРгос
(I: integer; il: integer = 1; i2: integer = 2);
В подобных случаях заключительные параметры при вызове процеду-ры можно опускать - они получат значения по умолчанию.
МуРгос (1, 2);
Реально процедура вызывается с тремя параметрами, как если бы ис-пользовался следующий оператор.
МуРгос(1,2,2);

Передача параметров по имени и по значению

Когда происходит обращение к подпрограмме, переменным, указанным в списке параметров в описании (формальные параметры), присваиваются значения, указанные в списке параметров в момент вызова (фактические параметры), после чего выполняются необходимые вычисления. Это называется передачей параметров по значению: в подпрограмму передаются значения нужных типов. Формальные переменные играют роль локальных переменных.
В списке параметров перед любой переменной разрешается указывать ключевое слово var. Тогда считается, что данный параметр будет передавать-ся по имени: то есть, копирования значения не происходит, а вместо фор-мального параметра подставляется имя переменной - фактического параметра. (Отсюда следует, что в качестве фактических параметров, подставляемых вместо формальных параметров с ключевым словом var, можно применять только имена переменных.)
Например:
procedure MyProc(X: Byte; var Y: Byte);
Параметр X будет передаваться по значению, параметр Y - по имени. При вызове
MyProc(2+2, N);
операторы в теле процедуры MyProc будут обрабатывать локальную переменную X, имеющую значение 4 (2+2), и переменную Y, которая на самом деле является переменной N из другой части программы. На «физическом» уровне произойдет просто подстановка адреса переменной N. Использование слова var в списке параметров по способу действия аналогично использованию указателя.
При этом если в теле процедуры значение переменной X будет ме-няться, то по окончании работы MyProc эта локальная переменная будет удалена из памяти (до следующего вызова процедуры), а вот если произойдет изменение значения переменной Y, то изменится и значение переменной N.
Это потенциально чревато ошибками, так как разработчик может не рассчитывать на то, что во время работы подпрограммы произойдет изменение значения одного из ее параметров. В данном случае переменная Y является не чем иным, как указателем на переменную N, только описан он немного иначе: не с помощью операции ^, а как обычная переменная.
Следует избегать передачи параметров по имени за исключением слу-чая, когда требуется передать в подпрограмму данные большого объема. На-пример, если описан тип
type TBigArray = array [1..100000] of string[50];
то передавать переменную этого типа по значению очень неэффективно, особенно если вызов подпрограммы происходит часто, потому что при этом требуется копировать большие объемы данных. То есть, описание
procedure Sum(A: TBigArray);
неудачно в плане эффективности (хотя компилятор может самостоятельно выполнить передачу параметра по имени в процессе автоматической оптимизации кода).
Правильнее написать так:
procedure Sum(var A: TBigArray);
При этом надо проследить, чтобы изменения элементов массива А внутри процедуры Sum не происходило (если этого не требует логика ее работы).

Параметры-константы

Если некоторый параметр будет использоваться в теле подпрограммы только для

считывания данных (фактически, как константа), лучше не рассчитывать на воз-

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

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

Подобная подсказка осуществляется указанием зарезервированного слова const

в списке параметров, что позволяет организовать эффективную обработку соот-

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

procedure Sum(const A; TBigArray),-

Менять значение элементов переменной А в теле процедуры Sum теперь нельзя:

компилятор сообщит об ошибке.

 

Параметры-результаты

В Паскале имеется еще одна возможность передачи параметра по имени - с помощью зарезервированного слова out. Такой параметр может использоваться внутри тела подпрограммы только для присваивания значения (но не для считывания данных). По смыслу использование слова out противоположно использованию слова const.
Если заголовок процедуры описан так:
Procedure Sum (out A: TBigArray);
То в теле процедуры Sum можно указывать операторы присваивания
A[10000]:= 'num172855';
Но нельзя считывать значения элементов массива A:
x:= A[2] * 2; // нельзя!
ПОДСКАЗКА. Для получения результатов от подпрограммы всегда правильнее использовать функции. Процедуры, возвращающие результат через свои параметры, лучше применять только тогда, когда без этого не обойтись (например, параметры-результаты требуются при создании приложений СОМ и CORBA)



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: