開発環境
Ruby 2.6.5
配列を代入した変数の正体
ある程度プログラミングを経験している方からすると当たり前のことだと思いますが、結構実装途中で意図しない挙動をするのでメモとして記録します。(一応技術書を参考にしてますが、違ったらご指摘ください)
コード実行
まず下記のコードの実行結果を予想してみてください。
array = [1,2,3]
array2 = array
array2[0] = 124
puts array[0]
実行結果は
124
になります。
ここで大事なのは配列の数字自体は変数に代入されていないという点です。
配列を代入した時の裏側
このとき裏側で起こっているのは配列の保存場所を示した番号が変数として代入されています。
このように保存場所を示す番号を参照して値を呼び出す変数を参照型変数と言います。
参照型変数の特徴は参照する番号が変数に入るので、複数の変数で1つの場所を指すことがあります。
上記の配列の例は
array = [1,2,3]
array2 = array
array2[0] = 124
puts array[0]
配列の保存場所を参照する番号を代入したarrayをarray2に代入しているので2つの変数の指す配列が同じになっています。
そのため、array2の配列を変更したと思ってもarrayも変更されているということです。
より詳しく
より詳しく伝えると、Rubyの場合すべてがオブジェクトであるので配列のみではなく整数なども参照型になります。
num = 1
array = [1,2,3]
上記のコードではnumには1というオブジェクトへの参照を代入されています。
arrayには1,2,3を参照したリストの参照を保存しています。
array = [1,2,3]
array2 = array
array2[0] = 124
このコードでは1,2,3を参照にしたリストオブジェクトに代入をしていることになります。
変数に直接代入をして参照先を変更するか
変数に入っているオブジェクトに代入をするか
この違いがあります。
追記
array = [1,2,3]
array2 = array
array2[0] = 124
puts array[0]
上記は参照型変数が代入されていると言いました。
もっとわかりやすく言うと通常の変数の代入とは全く違うということになります。
下記の2つは同じ意味になります。
array2[0] = 124
array2.[]=(0,124)
つまりarray2[0] = 124は**array2.[]=(0,124)**を簡潔に表した糖衣構文(シンタックスシュガー)ということになります。
簡潔に表した時に代入と同じに見えますが、実際には違うという点が重要ですね
まとめ
ここでまとめたことは当たり前すぎることだと思いますが、たまにおや?とおもうことがあるのでまとめておきました。
参考になることがあれば嬉しいです。