値渡しと参照渡しと参照の値渡しと部屋とYシャツと私

こんにちは!kossyです!





今回は値渡し・参照渡し・参照の値渡しの違いについて、ブログに残そうかなと思います。
なんとなく語呂が"部屋とYシャツと私"に似ているので、データとして登場して頂こうと思います笑

値渡しとは

関数の呼び出し元の変数の値をコピーし、呼び出し先で変数の中身を書き換えても呼び出し元には影響しない処理のことです。

こんな感じの処理です。

def song(room, shirt, i)
  room  = "夜勤と"
  shirt = "冷えたおにぎりと"
  i     = "俺"
  puts room + shirt + i
end

room  = "部屋と"
shirt = "Yシャツと"
i     = "私"

puts room + shirt + i
song(room, shirt, i)
puts room + shirt + i

実行結果

部屋とYシャツと私
夜勤と冷えたおにぎりと俺
部屋とYシャツと私(値が更新されてない)

呼び出し元で実引数をもたせて、関数で仮引数として受け取れる形にしたものですね。
Rubyをはじめとして多くの言語は値渡しのやり方を取っています。

参照渡しとは

調べてみると、メモリの領域がーとか出てくるんですが、メモリ領域に対するざっくりとした自分の理解は、
・変数はメモリ領域を個別に持っている
・引数に使われる変数もメモリ領域を持っている
・参照渡しの際には値を直接渡すのではなくて、変数のメモリ領域(住所)を渡す

ってな感じです。
詳しく知りたい方は参考文献を下の方にまとめてあるのでそちらをご覧ください。

参照渡しは、関数に渡される実引数と仮引数がメモリ上で同じ場所を指すようになるもので、
関数の呼び出し先で書き換えられた値が呼び出し元の値に反映されます。
イメージとしては、参照渡しは住所を渡して、その住所にある建物を壊してもいいし改築してもいいし、
何してもいいよ、的なイメージでしょうか。一回建物を破壊したり改築したら、完全に元には戻せないですよね?

まぁ正直理解が曖昧なのは否めませんので、間違っていたらご指摘いただきたいです・・・

参照の値渡しとは


これが一番よくわからんです。
参照するオブジェクトは一緒なんだけど、変数のメモリ領域(住所)が違うから参照の値渡しが起こるらしい。
Rubyだと、配列の値とかハッシュの値を書き換えるのが参照の値渡しに該当するんですかね。

コードで表現すると、

def song(room_shirt_i)
  room_shirt_i[0] = "夜勤と"
  room_shirt_i[1] = "冷えたおにぎりと"
  room_shirt_i[2] = "俺"
end

room_shirt_i = ["部屋と", "Yシャツと", "私"]

puts room_shirt_i[0..2]
song(room_shirt_i)
puts room_shirt_i[0..2]

=>
部屋と
Yシャツと
私
夜勤と
冷えたおにぎりと
俺

こう書けばこう動く、っていうのはわかるんですが、中でどういう処理なのかがいまいちピンと来てないです。
まとまりのない記事で申し訳ない・・・