2016年8月15日月曜日

参照渡しと値渡しの違い

参照渡し・値渡しの違いとはなんでしょうか。 以下のVBAの例を見ながらその違いを説明してみたいと思います。

まず気をつけないといけないのはあらゆるプログラミングにおける「変数」とは値とアドレスのペアで成り立っているということです。「値」だけ渡すのが値渡し、アドレスを渡すのが「参照渡し」です。

よく言われる話ですが「参照渡し」とは「アドレス(住所)」を渡すのです。なんの「住所」なのかといえば、「メモリ上の、データが格納されている場所」いわばデータのメモリ上の住所なのです。

メモリというのはRAMとも呼ばれますが、パソコンが何か作業をする際に一時的にデータを格納したりするのに使います。

例えてみると「机」のようなもので、例えばパソコンが1から100までの数字が並んだ数列の総和を求めるという仕事を与えられたとすると、その中途の式や和がメモリに格納されます。メモリは大まかにいえばこんな感じのものです。

 ・・・・○・

こんな風に「右から2番目」にデータが入っているなら、「右から2番目」という住所(アドレス)を渡すのが参照渡しです。

値渡しはデータの値を渡します。例えば、「5」というのが右から2番目のアドレスに入っているなら、「5」という値だけ渡します。

参照渡しと値渡しの違いを見てみましょう。

以下のコード(VBA)を見てください。

Sub test()
Dim a As String
a = "AAA"
test1 (a)
MsgBox ("ByVal: " & a)
test2 a
MsgBox ("By Ref: " & a)
End Sub
Sub test1(ByVal i As String) 'ByVal
i = "BBB"
End Sub
Sub test2(ByRef i As String) 'ByRef
i = "BBB"
End Sub



実行結果

ByValというのが値渡しです。ByRefというのが参照渡しです。ByValは値渡しなので、「変数aにAAAという値を代入→変数iに変数aの値を代入(値渡し)→変数iにBBBという値を代入→変数aの値を出力」という比較的単純な工程を辿ります。

ByRefは参照渡しです。なので「変数aにAAAという値を代入→変数iに変数aのメモリ上のアドレスを代入(参照渡し)→変数iにBBBという値を代入→変数aの値を出力」という工程を辿ります。すると、このときデータのアドレスが渡されているので、渡された先の変数(i)を変更すると渡し元の変数(a)の値も変更されるのがわかります。参照渡しをすることで2つの変数は同じメモリのアドレスを参照するようになるのです。

逆に値渡しの場合は、単に値がコピーされて、値のコピーが別の変数に渡されるだけなので、渡し先の変数の値を変えても渡し元の変数の値は変わりません。