自分はこれまでにJava, Goを勉強してきた。この二言語における値渡し/参照渡しをここで整理してしまう。
そもそも定義
-
値渡し
(call by value): メソッドの引数に、新たに値のコピーを作って渡す方法のこと。 -
参照渡し
(call by reference): メソッドの引数に、変数そのものの参照を渡す方法のこと。
Javaの場合
- メソッドへの引数は100%
値渡し
で渡される。 - が、Javaのオブジェクトが変数に収納されている時、そこに収納されているのは「そのオブジェクトが収納された場所を示す
参照値
(reference value)」である - よって、オブジェクトを引数として渡すときにはその
参照値
(reference value)のコピーが渡されている。 - この結果、「引数に渡したオブジェクトが参照渡しで書き換えられている」かのように勘違いしそうになる。
Goの場合
- ポインタを引数として渡すことで
参照渡し
を実現する。 - Golangの構造体/Arrayは(Javaのオブジェクトとは違って)
値型
。すなわちその全てのフィールド/要素を収納する場所を確保し、それを構造体を表す変数に収納しているイメージ。 - よって構造体を
値渡し
すると、そのフィールドの全てがコピーされる。これを書き換えても元の構造体は書き変わらない。 - 一方で、map/sliceは(Javaのオブジェクトと同様)
参照型
。すなわち変数に入っているのは要素のポインタが入った容器であり、各要素にアクセスするにはポインタを辿っているイメージ(参考)。 - このため、これらを
値渡し
したとしても、元のmap/sliceが書き換わってしまう。よって、普通これらをポインタ渡し
する意味はなく、普通そうしない(参考)。
補足
-
参照渡し ≒ ポインタ渡し
であるかのように書いたが、そこの細かいところはこちらに詳しい。 -
値型
/参照型
の説明は正確ではないかもしれないのであくまでイメージとして捉えてほしい。
参考
- もう参照渡しとは言わせない (だいぶ参考にさせていただきました)
- Goの値型と参照型