Параметры процедур и функций
Параметры, указываемые при описании
подпрограммы, называются формальными. Параметры, указываемые при вызове
подпрограммы, называются фактическими.
Если формальный параметр описан с
предваряющим ключевым словом
var или const , то его называют параметром-переменной и говорят, что
он передается по ссылке. Если же
параметр описан без слов var или const ,
то его называют параметром-значением и говорят, что он передается
по
значению.
Если параметр передается по значению, то при вызове
подпрограммы значения фактических параметров присваиваются соответствующим
формальным параметрам. Типы фактических параметров-значений должны быть
совместимы по присваиванию с типами
соответствующих формальных параметров.
Например, пусть имеется следующее описание процедуры:
procedure PrintSquare(i: integer);
begin
writeln(i*i);
end;
Тогда при вызове PrintSquare(5*a-b) значение 5*a-b будет вычислено и присвоено переменной i , после чего
выполнится тело процедуры.Если параметр передается по ссылке, то при вызове
подпрограммы фактический параметр заменяет собой в теле процедуры
соответствующий ему формальный параметр. В итоге любые изменения формального
параметра-переменной внутри процедуры приводят к соответствующим изменениям
фактического параметра. Фактические параметры-переменные должны быть
переменными, а их типы должны быть
эквивалентны типам соответствующих формальных параметров.
Например, если описана процедура
procedure Mult2(var
a: integer);
begin
a := a*2;
end;
то после вызова Mult2(d) значение d увеличится в 2 раза.В качестве фактического параметра-значения можно указывать
любое выражение, тип которого совпадает с типом формального параметра или неявно
к нему приводится. В качестве фактического параметра-переменной можно
указывать только переменную, тип которой в точности совпадает с типом
формального параметра.
При передаче параметра по ссылке в подпрограмму передается адрес фактического
параметра. Поэтому если параметр занимает много памяти (массив, запись), то
обычно он также передается по ссылке. В результате в процедуру передается не сам
параметр, а его адрес, что экономит память и время работы. При этом если
параметр меняется внутри подпрограммы, то он передается с ключевым словом
var , если не меняется - с ключевым словом const :
Например:
type
Person = record
name: string;
age,height,weight: integer;
end; procedure Print(const p: Person);
begin
write(p.name,' ',p.age,' ',p.height,' ',p.weight);
end;
procedure IncAge(var p: Person);
begin
Inc(p.age);
end;
Отметим особенности передачи строк и динамических массивов в
качестве параметров подпрограмм.
Поскольку динамический массив является ссылкой, то при
изменении формального параметра-динамического массива внутри подпрограммы
меняется соответствующий фактический параметр. Например,
в результате работы программы
procedure p(a: array of integer);
begin
a[1] := 2;
end;
var b: array of integer := (1,1);
begin
p(b);
writeln(b[1]);
end.
будет выведено 2. Передавать динамические массивы по ссылке
имеет смысл только в случае если память под динамический массив
перераспределяется внутри подпрограммы:
procedure q(var a: array of integer);
begin
SetLength(a,10);
end;
Несмотря на то, что строки являются ссылочным типом данных (а
значит, присваивание строк и передача их по значению выполняется быстро - без
копирования содержимого строки), любое изменение строки приводит к созданию
новой строки. Например, после выполнения кода
var s: string := 'abc';
s[2] := 'd';
память под строку s будет
перераспределена, и ссылка s будет указывать
на новый участок динамической памяти. Это приводит к тому, что строки, несмотря
на свою ссылочную природу, ведут себя при передаче параметров как размерные
типы: Например, в результате выполнения кода
procedure r(s: string);
begin
s[2] := 'd';
end;
var ss: string := 'abc';
begin
r(ss);
writeln(ss[2]);
end.
будет выведено 'b', что означает, что
фактический параметр не изменился. Поэтому строки при передаче по значению ведут
себя как размерные типы.
|