コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

Rubyの引数の情報の渡り方(共有渡し)をざっくりまとめる

いまいちちゃんと理解していなかったので改めてまとめる

大前提としての値渡し、参照渡し

プログラミング言語の引数の渡り方の話で出てくるフレーズなので説明としては簡素に記述するが

  • 値渡しは呼び出し元の実数値(実引数の値)を呼び出した関数の引数(仮引数)に渡す方式
  • 参照渡しは呼び出し元の引数の保存されている領域の情報元の実数値(実引数の参照情報)を呼び出した関数の引数(仮引数)に渡す方法

Rubyでは参照の値渡し(≒共有渡し)

るびまに以下のような記事がある。

値渡しと参照渡しの違いを理解する

こちらより引用すると

Ruby (や多くのプログラミング言語) は値渡しである。
・変数が参照 (= メモリ番地) を保持している場合は、それが引数にコピーされる。
・そのため、変数 (実引数) と引数 (仮引数) とが同じオブジェクトを共有することになるので、引数が指すオブジェクトを変更すると、もとの変数のオブジェクトも変更される。
・「変数を変更する」ことと「変数が指すオブジェクトを変更する」ことは別である。

というように値渡しが基本ではあるが、変数に入っている実態数値がセットされているわけではなく、「参照の情報が値渡しされている」という表現になっている

具体的にはどういうことか

純粋な値渡しの例

例えば下記のような処理を書く

def irekae(a,b)
  temp_a = a
  temp_b = b
  a = temp_b
  b = temp_a
end

下記を実行してもaとbの値は入れ替われない。

a = 200
b = 100
irekae(a,b)
pp a
pp b

上記の実行結果は以下となる

200
100

参照の値渡しの例

参照をしている情報を渡しているだけなので、参照先のオブジェクトの中身を変更すると値が変更となる。配列の例は参考サイトにもあるのでオブジェクトの例を下記に示す。

まずは利用するクラスを定義する

class Monoire
  def initialize(value)
    @atai = value
  end

  def set_atai(value)
    @atai = value
  end

  def get_atai
    return @atai
  end
end

そして下記のように利用する

def change_monoire(target)
  target.set_atai(200)
end

temp = Monoire.new(100)
pp "before atai = #{temp.get_atai}"
change_monoire(temp)
pp "after atai = #{temp.get_atai}"

そうすると下記のような出力結果となりtempはメソッドでの処理の影響を受ける。

"before atai = 100"
"after atai = 200"

参考サイト

参照の値渡しと共有渡しに関しては呼び方にいろいろあるので参考サイトを読んで頂くとよさそう。