1
0

最近勉強して出てきたshallow copyについて、まとめてみます。
新米エンジニアなので、誤りがあったらご指摘ください:santa:

shallow copyとは

かなりざっくり「外見は別物だけど、中身は一緒だよ」というコピー

  • aオブジェクトと、それをコピーしてできたbオブジェクトがあった場合...

    1. aオブジェクトとbオブジェクトは、別々のobject_idだよ(外見は別物)
    2. aオブジェクトとbオブジェクトが指してるオブジェクト(配列の要素など)の参照先は一緒だよ(中身は一緒)

というコピーのこと。

Rubyだと、clonedupshallow copyができます。

文字だけだと何を言っているか分かりにくいので、次にいきましょう。

見てみよう

※分かりやすくするために、object_idをメモリの番地としています。(object_idは適当です)

1. shallow copy元と、copy先のobject_idは別々ある(外見は別物)

a = ["a", "b", "c"]
b = a.clone

# 外見は別物
p a.object_id  # 60
p b.object_id  # 80

スクリーンショット 2024-06-30 10.30.22.png

2. shallow copy元と、copy先が指してるオブジェクトの参照先は一緒(中身は一緒)

a = ["a", "b", "c"]
b = a.clone

# 外見は別物
p a.object_id  # 60
p b.object_id  # 80

# 中身の参照先は一緒
p a[0].object_id  # 10
p b[0].object_id  # 10

p a[1].object_id  # 20
p b[1].object_id  # 20

p a[2].object_id  # 30
p b[2].object_id  # 30

スクリーンショット 2024-06-30 10.33.26.png

外見が違うと

外見が違う(object_idが異なる)ので、aオブジェクトに対する変更(外見に対する変更)は、bオブジェクトに影響を及ぼしません。

  • aオブジェクトに要素"d"を追加する
a = ["a", "b", "c"]
b = a.clone

a.push("d")

p a  # ["a", "b", "c", "d"]
p b  # ["a", "b", "c"]

p a[3].object_id  # 40

スクリーンショット 2024-06-30 10.47.53.png

  • aオブジェクトの[0]要素の参照先を変更する
a = ["a", "b", "c"]
b = ary.clone

a[0] = "d"  # 破壊的な変更ではなく、参照先の変更なので、新しいオブジェクトが作られる

p a  # ["d", "b", "c"]
p b  # ["a", "b", "c"]

p a[0].object_id  # 40

スクリーンショット 2024-06-30 10.53.35.png

中身が一緒なので

こんなことが起こります。

参照先に破壊的な変更を加えると、両方とも変わる

a = ["a", "b", "c"]
b = ary.clone

# 参照先に破壊的変更を加える
a[0].upcase!

p a  # ["A", "b", "c"]
p b  # ["A", "b", "c"]

スクリーンショット 2024-06-30 10.35.37.png

そもそも=cloneの違い

ここで、=の挙動も見て、cloneとの違いを確認しましょう。

a = ['a','b','c']
b = a  # aが参照しているのと同じメモリ番地にある['a', 'b', 'c']を、bも参照するようになる

p a.object_id  # 60
p b.object_id  # 60

スクリーンショット 2024-06-30 11.08.07.png

参考

shallow copyについて


メモリ?番地?参照?という方へ

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0