質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

4回答

6229閲覧

Rubyで参照渡しのような挙動が発生する事象について

GOROGORO

総合スコア66

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

1クリップ

投稿2016/04/26 07:54

ruby2.1.1の環境において、以下のようなコードを実行します。

ruby

1hashA={"test"=>"aaaa"} 2arrayA=Array.new 3#ハッシュを配列に格納 4arrayA.push(hashA) 5p hashA 6#配列に投入したハッシュの値を変更 7arrayA[0]["test"]="bbbb" 8p hashA

実行結果

{"test"=>"aaaa"} {"test"=>"bbbb"}

arrayA.push(hashA)
を実行したときにhashAそのものが配列に渡されているようで、
配列の中の値を変更したときにhashAそのものの値も変更されてしまっています。

配列の中にはhashAのコピーを渡して、
配列の中を更新しても、hashAそのものは更新させたくないのですが、どのように記述すればよいでしょうか?

また、rubyは基本値渡しであると理解しているのですが、なぜこのような参照渡しのような動作をするのでしょうか?

どうぞよろしくお願いします!!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

配列の中にはhashAのコピーを渡して

ruby

1hashA={"test"=>"aaaa"} 2arrayA=Array.new 3#ハッシュを配列に格納 4arrayA.push(hashA.clone) 5p hashA #=> {"test"=>"aaaa"} 6#配列に投入したハッシュの値を変更 7arrayA[0]["test"]="bbbb" 8p hashA #=> {"test"=>"aaaa"}

rubyは基本値渡しであると理解しているのですが、なぜこのような参照渡しのような動作

「参照渡し」と「参照の値渡し」は違います。
これは「参照の値渡し」です。

投稿2016/04/26 08:15

ozwk

総合スコア13551

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

少し調べてみましたが、こちらの記事この方の記事が参考になりました。参照の値渡し

hashAそのものの値も変更とありますが、指している値を直接変えるので
参照先の値が変わるという解釈で良いと思います。

hashAが指している位置は1つしかないので、値だけを渡すならば
関数を使っては如何でしょう。

def test(hashA) #この時点で新しいメモリに値が移ります #ハッシュを配列に格納 arrayB=Array.new arrayB.push(hashA) return arrayB end hashA={"test"=>"aaaa"} p hashA arrayA=Array.new arrayA = test(hashA) #配列に投入したハッシュの値を変更 arrayA[0]["test"]="bbbb" p hashA

投稿2016/04/26 08:43

編集2016/04/26 10:06
toshi_yama

総合スコア133

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ruby

1arrayA.push(hashA.clone())

のように、hashAをcloneしてから値を変更すると質問の現象を回避できます。

たとえば、

ruby

1hoge = [aa, bb, cc] 2fuga = hoge 3 4puts fuga #=> [aa, bb, cc] 5fuga << [dd] 6puts hoge #=> [aa, bb, cc, dd]

このようなコードがあったとして、hogeをfugaに代入してからputsでfugaを出力します。
fugaはhogeを代入したのであって、コピーしたのではないのであくまでも参照の値渡しになっています。

なのでfugaの値を変更するとその参照先であるhogeの値を変更してしまっているらしいです。
私も自分なりの理解なので間違っている箇所もあるかと思いますが、大体こんな感じの挙動かと。

dupとかcloneとかMarshalとかのキーワードでググると色々出てくるので調べてみてください。

投稿2016/04/26 08:13

編集2016/04/26 08:45
ShoheiUyama

総合スコア206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

また、rubyは基本値渡しであると理解しているのですが、なぜこのような参照渡しのような動作をするのでしょうか?

オブジェクトへのポインタの値渡しです。なので、値渡しか参照渡しか二者択一と言われると、参照渡しですね。
なぜ値渡しと思ったのでしょうか?

どのように記述すればよいでしょうか?

この場合だと、hashA.dupをpushすればいいですが、一般にはコピーを作るのは簡単ではないです。
どう難しいかは、「ディープコピー」「シャロウコピー」について調べてみて下さい。

投稿2016/04/26 08:12

編集2016/04/26 14:08
otn

総合スコア85778

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問