seegongsik
プログラミング

参照 メモリ わかりやすく

プログラムが動いているあいだ、私たちが作った値はどこかに必ず入っていなければなりません。その場所がメモリです。番号のついたロッカーがずらりと並んだ壁を思い浮かべてください。名札は、そのうちのどのマスかを指すメモです。

01

値はどこかに入っている

プログラムが動いているあいだずっと、すべての値はメモリのどこかに場所を取っています。
メモリは、番号のついたロッカーがずらりと並んだ壁のようなものです。
値を一つ作ると空いたマスに一つすっと入り、プログラムはその値を「何番のマス」として覚えます。

マス 1
マス 2
マス 3
マス 4
マス 5

「値を入れる」を押すと、空いたマスに値が一つ入り、マスの番号が表示されます。

値ごとに自分のマスと番号ができました。
でもコードでは「7番のマス」とは書かず、'a'や「点数」のような名前を使います。
では、その名前とマスの番号はどうつながっているのでしょうか。

02

名札は場所を指す

名前は値そのものではなく、どのマスかを知っているメモです。
名前 'a' → 3番のマス → その中の7。
だから'a'を使うと、プログラムはメモをたどって3番のマスを開け、7を読みます。これが「指す」ということです。

a
→
マス 3
7

「aをたどる」を押すと、メモをたどってマスへ行き、中の値を取り出します。

名前がマスを指し、そのマスの中に値があります。
この指し示すメモを、参照と呼びます。
ここからが本当に大事です。「aをbにも渡す」と、何が起きるでしょうか。

03

小さな値はコピーされる

数のような小さな値をbに渡すと、その値が新しいマスにそっくり複製されます。
これでaは3番のマス、bは5番のマスと、別々のマスです。
だからaを9に変えても、bは7のままです。二つはそれぞれ自分の値を持つ、独立した関係なのです。

a
→
マス 3
7

「bにコピー」のあと「aを変える」を押すと、bは別のマスなので変わりません。

コピーされた小さな値は互いに影響しないので、すっきりしています。
けれどもオブジェクトのような大きなものは、事情が違います。大きなものをまるごと複製するのは重いからです。
そこでふつうは、コピーのかわりに別のことが起こります。

04

大きなものは同じ場所をいっしょに指す

オブジェクトをbに渡すときは、オブジェクト全体を複製せず、ふつうはbにも同じマスを指させます。
これで、aとbという二枚のメモが、一つのマスをいっしょに指しています。
だからaでそのオブジェクトを直すと、bから見ても同じように変わっています。一つの物に名前が二つあるからです。

a
↓
マス 4
オブジェクト: 1

「b = a」のあと「aで直す」を押すと、同じマスなので、bで見ても変わっています。

二つの名前が一つのマスを指しているので、片方を直すと両方が変わります。
プログラムを学びはじめたとき、いちばんよく驚くところです。「さわってもいないbが、なぜ変わったの?」
もう答えはわかります。同じマスを指していたからです。

05

何を指しているかがわかれば、もう迷わない

迷いの正体は、いつも一つです。
名前が自分のコピーを持っているのか、それとも一つの物をいっしょに指しているのか。
小さな値ならコピーなので別々に動き、大きなものなら同じ場所を指していっしょに動きます。
この区別さえ思い出せば、驚くことはなくなります。

「小さな値」と「大きなもの」を選んで同じことをさせると、結果が分かれます。

ここまでが、プログラミングの土台です。
値一つから始めて、まとめ、繰り返し、名前をつけ、オブジェクトに集め、デバッグで直し、機械に動かさせました。
そしていま、そのすべてがどこに入っていて、名前が何を指しているのかまで見たので、しっかりした土台ができたのです。

一言でいうと値はメモリの一つのマス(アドレス)に入っていて、名前はそのマスを指すメモです。小さな値をほかの名前に渡すと新しいマスにコピーされて互いに独立しますが、大きなもの(オブジェクト)はふつう同じマスをいっしょに指すので、片方を直すともう片方もいっしょに変わります。だれが何を指しているかがわかれば、その迷いは解けます。
← プログラミング
このページがお役に立ったなら支援する