Czyli jeżeli zdefiniowałbym zmienne l, p w funkcji odpowiedz, a potem przekazał je przez wartosc do funkcji ilew, to za kazdym razem gdy wywołuje rekurencję tworzona by była nowa kopia l,p ?
Tak, lokalna kopia parametru z poprzedniego wywołania; Więc tyle kopii parametru, ile rekursyjnych wywołań funkcji;
Zobacz na poniższy kod - realizuje on rekurencyjne odliczanie i wyświetlanie adresu parametru w postaci liczby heksadecymalnej:
uses
SysUtils;
var
intGlobalVariable: Integer = 0;
procedure GlobalVariableTest();
begin
WriteLn('Variable addr: $', IntToHex(LongInt(@intGlobalVariable), 0));
if intGlobalVariable < 3 then
begin
Inc(intGlobalVariable);
GlobalVariableTest();
end;
end;
var
intByRefVariable: Integer = 0;
procedure ParamByRefTest(var AParam: Integer);
begin
WriteLn('Param addr: $', IntToHex(LongInt(@AParam), 0));
if AParam < 3 then
begin
Inc(AParam);
ParamByRefTest(AParam);
end;
end;
procedure ParamByValueTest(AParam: Integer);
begin
WriteLn('Param addr: $', IntToHex(LongInt(@AParam), 0));
if AParam < 3 then
begin
Inc(AParam);
ParamByValueTest(AParam);
end;
end;
procedure ParamByConstTest(const AParam: Integer);
begin
WriteLn('Param addr: $', IntToHex(LongInt(@AParam), 0));
if AParam < 3 then
ParamByConstTest(AParam + 1);
end;
begin
GlobalVariableTest();
WriteLn;
ParamByRefTest(intByRefVariable);
WriteLn;
ParamByValueTest(0);
WriteLn;
ParamByConstTest(0);
ReadLn;
end.
Wyjście:
Variable addr: $409298
Variable addr: $409298
Variable addr: $409298
Variable addr: $409298
Param addr: $40929C
Param addr: $40929C
Param addr: $40929C
Param addr: $40929C
Param addr: $12FFA4
Param addr: $12FF88
Param addr: $12FF6C
Param addr: $12FF50
Param addr: $12FFA4
Param addr: $12FF88
Param addr: $12FF6C
Param addr: $12FF50
Procedura GlobalVariableTest
operuje na globalnej zmiennej intGlobalVariable
, inkrementuje ją i przekazuje do kolejnych wywołań; W każdym rekursyjnym wywołaniu procedury, nie jest tworzona żadna kopia - dostęp uzyskiwany jest bezpośrednio, więc bez względu na poziom rekurencyjnego zagłębienia, molestowana jest jedna zmienna;
Drugi przykład to procedura ParamByRefTest
- ona także korzysta ze zmiennej globalnej, ale za pośrednictwem parametru; Zmienna przekazywana jest do kolejnych wywołań przez referencję, więc tak samo jak wcześniej - operuje tylko i wyłącznie na jednej instancji zmiennej, do której dostęp uzyskuje przez parametr;
Trzecia procedura to ParamByValueTest
, która pobiera w parametrze liczbę przez wartość; Tworzona zostaje nowa "zmienna", dlatego że w takim przypadku, można przekazać samą wartość - nie musi to być zmienna; W każdym kolejnym wywołaniu tworzona jest kolejna zmienna, więc adres parametru w każdym rekurencyjnym wywołaniu będzie inny;
Ostatnia procedura to ParamByConstTest
- ona przyjmuje liczbę w parametrze przez stałą; W tym przypadku także tworzona jest nowa kopia dla każdego rekursyjnego wywołania, dlatego też adresy parametru będą różne;
Wszystkie procedury działają inaczej i dają różne możliwości:
-
GlobalVariableTest
- nie posiada parametrów, więc musi mieć dostęp do zmiennej; ponadto wprowadzone zmiany mają zasięg globalny,
-
ParamByRefTest
- skoro pobiera liczbę przez referencję, trzeba podać jej zmienną, której sama widzieć nie musi; tak samo jak w powyższej - wprowadzone zmiany mają zasięg globalny,
-
ParamByValueTest
- pobiera liczbę w parametrze przez wartość, więc nie potrzebuje zmiennej; w każdym kolejnym wywołaniu tworzy kopię parametru, a zmiany mają zasięg lokalny,
-
ParamByConstTest
- pobiera liczbę przez stałą i tak samo nie potrzebuje zmiennej, też w każdym wywołaniu tworzy kopię parametru, jednak nie umożliwia modyfikowania jego wartości.