見出し画像

【図解】C++と絵で理解するこわくないポインタ

ポインタで混乱している人へ

最近こちらの記事を見て、今まで理解していたはずなのにまた頭がこんがらがり始めたので整理してみました。
絵的な解説をしてみました。

絵で見てみる

いつもの変数を「通常変数の世界」としたとき
アドレスは実家の住所になります。これはわかります。

ポインタは、個人的に一番わかりやすい解釈がホテルの住所でした。
ホテルの住所を持っておいてる人(変数)がいるんです。なので、その人にも実家があるんです。

まずは通常の変数、アドレスを見てみましょう。

.cpp

int a = 5;

とした場合、そのアドレスは &aで参照できるので

.cpp

std::cout << &a << std::endl; // 結果が「0x1040a0d0」(赤字)

これはわかる。

次にポインタ。

.cpp

int*b;

とすると、値にはアドレスが入る。

.cpp

std::cout << b << std::endl; // 結果が「0x102c7c000」(緑字)

いつもの世界の変数に行くためには

.cpp

*b = 5;

また、ポインタbも変数なので

.cpp

std::cout << &b << std::endl; // 結果が「0x16d18f410」(ピンク字)

キャラをつけてみる

アドレスがややこしくなってきたので、ちょっと分かりやすくキャラクターをつけてみましょう。
遊び人である*b君のホテル住所を覚えておいてくれる、執事的な人がbさんです。

ポインタとは、坊ちゃんのために住む場所を確保しておくもので
ポインタも人間(変数)なので、ポインタそのものの実家があります。

ここでは10という値をぼっちゃんがホテルに置いていて(アドレスに格納していて)
ぼっちゃんのホテルの住所0x102c7c000という値を執事の実家に持ってます(アドレスに格納しています)
よって「執事の実家、にある値」は「ぼっちゃんのホテルの住所」と同じであり
言い換えると*&bbと同じです。

.cpp

std::cout << *&b << std::endl; // 執事の住所、にある値
std::cout << b << std::endl; // ぼっちゃんのホテルの住所

&は住所、*をつけるとそのアドレスに入っている値をとる、という動作的にみても、
*&bbと同じはずですね。

ポインタ渡し

引数にbというポインタを入れる(=ポインタ渡し)関数があったとしましょう。
この時内部で、以下のような操作をしたとします。

.cpp

void test(int *arg) {
  int a = 5;
  arg = &a;
}

ここでポインタにアドレスを代入、すなわち執事bにaのアドレスを代入する
という動作について見ていきましょう。

.cpp

b = &a;

と代入をするとどうなるでしょう。

執事の値 = ぼっちゃんのホテルの住所に、aの住所を代入したので
ぼっちゃんは今度から、aの家に住むことになります。

つまりぼっちゃんはホテルに置いていた値10を手放して、aの家に住むことにしたので

.cpp

std::cout << *b << std::endl; // 結果は「5」になる

というように値が変わります。執事は傍観してます。

どう活かすか

図やイメージが膨らむ理解をしたかったので、つたないながらも絵でまとめてみました。
この上で、こちらの記事などで〜〜渡しを考えてみると分かりやすいかと思います。

個人的にはこうです。

  • 値渡し → おそらくみんな普通のやつだな〜と理解してそう

渡された変数の値が別のアドレスにコピーされる。だから、関数内で変更しても、呼び出しもとの変数の値は変化しない。

  • ポインタ渡し → 執事経由で、ぼっちゃんのホテル住所を変えて値を変える(本記事で絵にした話)

渡された変数のアドレスを指すポインタが別のアドレスに割り当てられてそれを通じて呼び出し元の変数の値を操作できる。だから、関数内で変更すると、呼び出し元も変更される。

  • 参照渡し → 住所渡す

渡された変数は呼び出し元の変数と値、アドレス含め全く同じになる。これはコピーではないので当然関数ないで変更すると呼び出し元の値も変化する。

ALHについて知る



↓ ↓ ↓ 採用サイトはこちら ↓ ↓ ↓


↓ ↓ ↓ コーポレートサイトはこちら ↓ ↓ ↓


↓ ↓ ↓ もっとALHについて知りたい? ↓ ↓ ↓