値渡しの場合、関数を呼び出すときに渡される値は、実際にはそのコピーが渡されます。
procedure MyProc(X: Integer); // X は値渡し begin Inc(X, 10); Form1.ListBox1.Items.Add('MyProc 内: ' + IntToStr(X)); // 110 end; procedure TForm1.Button1Click(Sender: TObject); var X: Integer; begin X := 100; ListBox1.Items.Add('Button1Click 内: ' + IntToStr(X)); // 100 MyProc(X); ListBox1.Items.Add('Button1Click 内: ' + IntToStr(X)); // 100 end;
関数 MyProc のパラメータ X は値渡しで渡されます。値渡しで渡された場合、実際にはそのコピーが渡されます。 したがって、コピーに変更を加えても呼び出し元の値は変化することはありません。Button1Click 内でまず初めに 変数 X に 100 を代入しています。X の値をリストボックスに表示すると、100 と表示されます。それから、MyProc 関数を呼び出しています。MyProc 内で、X の値を 10 だけインクリメントし、再びリストボックスに X の値を表示されると、当然 110 と表示されます。MyProc 関数を呼び出した後で、再び Button1Click 内で X の値を表示しています。そこでは、X の値は 100 と表示されます。MyProc 関数を呼び出すときに X を「値渡し」で渡しました。値渡しで渡された場合には、実際にはそのコピーが渡されるので、呼び出し元の値には影響を受けません。
参照渡しでは、値渡しのようなコピーの作成が行われません。関数本体内で、参照渡しで渡されたパラメータに加えられた変更は、呼び出し元にも影響を与えます。
procedure MyProc(var X: Integer); // X は参照渡し begin Inc(X, 10); Form1.ListBox1.Items.Add('MyProc 内: ' + IntToStr(X)); // 110 end; procedure TForm1.Button1Click(Sender: TObject); var X: Integer; begin X := 100; ListBox1.Items.Add('Button1Click 内: ' + IntToStr(X)); // 100 MyProc(X); ListBox1.Items.Add('Button1Click 内: ' + IntToStr(X)); // 110 end;
MyProc のパラメータ X は参照渡しです。パラメータに var を付けると参照渡しになります。 Button1Click 内で、まずはじめに変数 X に 100 を代入し、その値をリストボックスに表示させています(100 と表示される)。それから MyProc 関数を呼び出し、引数として X を渡しています。X は参照渡しで渡されます。値渡しと異なりコピーは作成されません。その為、MyProc 関数本体内で、そのパラメータに加えられた変更は呼び出し元にも反映されます。MyProc 関数本体内で X の値を 10 だけインクリメントしています。Button1Click に制御が戻ってから、X の値をリストボックスに表示させると 110 と表示されます。
変数のアドレスを表示させるということは、その変数が格納されているメモリのアドレスを表示させるということだと考えましょう。変数のアドレスを表示させるのに Format 関数を使用しています。@ 演算子は、変数のアドレスを返しますので、例えば、変数 X があった場合、@X は X のアドレスが返されることになります。
procedure MyProc(X: Integer); // X は値渡し begin Inc(X, 10); Form1.ListBox1.Items.Add(Format('MyProc 内 %p', [@X])); end; procedure TForm1.Button1Click(Sender: TObject); var X: Integer; begin X := 100; ListBox1.Items.Add(Format('Button1Click 内: %p', [@X])); MyProc(X); ListBox1.Items.Add(Format('Button1Click 内: %p', [@X])); end;
実行結果は次の通り。MyProc 内の X のアドレスが異なっているのが分かります。
procedure MyProc(var X: Integer); // X は参照渡し begin Inc(X, 10); Form1.ListBox1.Items.Add(Format('MyProc 内 %p', [@X])); end; procedure TForm1.Button1Click(Sender: TObject); var X: Integer; begin X := 100; ListBox1.Items.Add(Format('Button1Click 内: %p', [@X])); MyProc(X); ListBox1.Items.Add(Format('Button1Click 内: %p', [@X])); end;
実行結果は次の通り。このように参照渡しで渡された場合には、そのアドレスにも変化がない事が分かります。