2009年09月08日

Rubyでディープコピー

Rubyでオブジェクト(配列)を変数に代入すると、「shallow copy(浅いコピー)」されます。
これは、C++で言う参照コピーであり、Cで言うポインタ渡しと同じ挙動です。

◆exp. shallow copy

a = [0,1,2]
b = a
b[1] = 3

p "a = " + a.to_s
p "b = " + b.to_s

実行結果は、

"a = 032"
"b = 032"

となります。『"a = 012"』で無い所に注意が必要。 shallow copyなのでbを変更すると
コピー元のaも変更されます。 では、bを変更しても『"a = 012"』としたい場合はどうするか。
『deep copy(深いコピー)』すれば良いのです。 deep copyを実装するのに
Marshalモジュールを使います。

Rubyリファレンスマニュアル#Marshal

◆exp. deep copy

a = [0,1,2]
b = Marshal.load(Marshal.dump(a))
b[1] = 3

p "a = " + a.to_s
p "b = " + b.to_s

実行結果は、

"a = 012"
"b = 032"

となり、コピー先bを変更してもコピー元aには影響が出ません。 やっている事は、

Marshal.dump(a)

でマーシャルデータ(オブジェクトをファイルに書き出す際のデータ)を作成して、

b = Marshal.load(Marshal.dump(a))

作成したマーシャルデータをloadしてオブジェクトに戻したものを代入。loadする際に新規にオブジェクト
が生成されるので、deep copyとなるわけです。

deep copyは良く使いそうなので、

def deep_copy(obj)
Marshal.load(Marshal.dump(obj))
end

とかで関数定義しておくと便利そうです。 というか良く使いそうなのでRuby言語側で実装して欲しいm(_ _)m


posted by purigen at 00:56| Comment(0) | TrackBack(0) | Ruby | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。