【プログラミング】値渡しと参照渡しの違い
おはようございます。おーみんです。
値渡しと参照渡しの違い
プログラミングの勉強をしていると「値渡し」と「参照渡し」の比較が結構な確率で出てくるかと思います。
僕は今でこそ理解してきましたが、勉強したばかりの頃はなかなか理解できませんでした。
そこでこの際しっかりまとめておこうと思います。
参考文献
『実戦で役立つC#プログラミングのイディオム/定石&パターン』 出井秀行 著
※この本に関する過去記事も書いていますのでぜひ!
『実戦で役立つC#プログラミングのイディオム/定石&パターン』を読んだ感想。 - おーみんだよ。
値渡し
以下のコードを見てみましょう。
----------
MyPoint a = new MyPoint(10,20);
MyPoint b = a;
Console.WriteLine("a: ({0},{1})", a.X, a.Y);
Console.WriteLine("b: ({0},{1})", b.X, b.Y);
a.X = 80;
Console.WriteLine("a: ({0},{1})", a.X, a.Y);
Console.WriteLine("b: ({0},{1})", b.X, b.Y);
----------
※MyPointは構造体です。
実行結果は以下のようになります。
----------
a: (10,20)
b: (10,20)
a: (80,20)
b: (10,20)
----------
これは値を渡しているので単純に「a.X=80;」の部分でa.Xの値のみ変更されています。
参照渡し
それでは同様のコードで参照渡しを見てみましょう。
----------
MyPoint a = new MyPoint(10,20);
MyPoint b = a;
Console.WriteLine("a: ({0},{1})", a.X, a.Y);
Console.WriteLine("b: ({0},{1})", b.X, b.Y);
a.X = 80;
Console.WriteLine("a: ({0},{1})", a.X, a.Y);
Console.WriteLine("b: ({0},{1})", b.X, b.Y);
----------
※MyPointはClassです。
実行結果は以下のようになります。
----------
a: (10,20)
b: (10,20)
a: (80,20)
b: (80,20)
----------
あれ!?「a.X=80」でa.Xのみ値を変換したはずなのにb.Xの値まで変換されています。
それぞれの仕組み
これは値渡しが値自体を設定するのに対し、参照渡しは値を格納している場所を設定しているからこそ起きることなのです。
上記で紹介した本の図が分かりやすいかもですね。
これが値渡しだと「~番地」とかはなく、各々で「X:10, Y:20」となっているのです。
そりゃa.X=80とaの値のみ変えられたらb.Xの値は10のままですよね。
参照渡しでは上の写真の通り番地を変数に格納しているため、その番地先にあるXの値が「a.X=80」によって変更されたらb.Xの値も変わります。
なぜ値型と参照型が必要なのか?
なぜわざわざ値型と参照型があるのでしょうか?
それは実行効率とメモリ効率が関係しています。
値型だと、大きなサイズのオブジェクトを使う際にいちいち各々の値を用意しなくてはいけません。これが参照型なら番地さえ用意すれば値は一つですみます(まさに上に載せた写真のように)。
しかしながら参照型だと、今度は小さなサイズのオブジェクトを使う際に無駄が発生します。要は番地と値自体のセットなのでわざわざ小さなサイズのオブジェクトにセットを使うよりは値型で値だけポーンと用意したほうが無駄が少ないのです。
というように、どちらにもそれぞれの用途があるのですね。
最後に
値渡しと参照渡しはなかなか最初からすんなりとは理解出来ないかもしれません。
とはいえ、かなり大切な内容ですのでこの際粘って理解していきましょう!
では!