配列を引数にするときの注意

配列を引数にするときの注意事項

配列引数はByRefでなければなりません

SubとかFunctionの引数に配列を使用しようとしたとき、「ByVal」キーワードを付けると、

f:id:akashi_keirin:20180327160042j:plain

こんなふうにコンパイル・エラーになる。

従って、引数を配列にしたときには必然的に参照渡しになってしまう、ということだ。

配列を加工して返すFunctionを使用した場合

……ということは、配列を受け取って、加工して返すようなFunctionを使用した場合、もはや元の(加工前の)配列は存在しない、ということなのだろうか。

やってみた

次のコードで実験。

リスト1 標準モジュール
Public Sub testTemperArray()
  Dim ar(3) As String
  ar(0) = "アホ"
  ar(1) = "ボケ"
  ar(2) = "クズ"
  ar(3) = "デコスケ"
  Dim el As Variant
  Debug.Print "【arの要素書き出し】"
  For Each el In ar    '……(1)'
    Debug.Print el
  Next
  Dim ar2() As String
  ar2 = temperArray(ar)    '……(2)'
  Debug.Print "【ar2の要素書き出し】"
  For Each el In ar2    '……(3)'
    Debug.Print el
  Next
  Debug.Print "【再びarの要素書き出し】"
  For Each el In ar    '……(4)'
    Debug.Print el
  Next
End Sub

Private Function temperArray(ByRef targetArray() As String) As String()
  targetArray(2) = "KASU"
  temperArray = targetArray
End Function

「temper」というのは、今はやりの「改竄する」という意味w

受け取った配列の第3要素を「KASU」というイカしたローマ字に改竄して返すプロシージャだ。

まず、冒頭で作成したarという要素数4の配列について、(1)からの3行

For Each el In ar
  Debug.Print el
Next

で、For Eachを使って全要素をイミディエイトに書き出す。

次に、(2)の

ar2 = temperArray(ar)

で、バカ丸出しのFunctionプロシージャ「temperArray」に配列arを渡して、返り値をar2にぶち込む。

そして、(3)からの3行

For Each el In ar2
  Debug.Print el
Next

で、ar2の要素をイミディエイトに書き出す。

あとは、(4)からの3行

For Each el In ar
  Debug.Print el
Next

で、再度arの全要素をイミディエイトに書き出す。

実行結果

f:id:akashi_keirin:20180327160049j:plain

arを引数として渡して加工したときに、arそのものが加工されてしまったっぽい。まさに参照渡し。

おわりに

気をつけないといけないなあ。

@akashi_keirin on Twitter