<目次>
(1) C++の「int **g = new int*;」の意味について
(1-1) 「int **g = new int*;」の意味
(1-2) サンプルで理解を深める
(1) C++の「int **g = new int*;」の意味について
C++を学ぶ中で「int *g = new int;」の左辺はポインタで、右辺の動的メモリ確保(≒要素1個の配列)の先頭のポインタのアドレスを保持しているといったイメージを持たれていると思います。
⇒(参考)
C++の動的メモリ割当と静的メモリ割当の違いについて
(図100)左辺のアスタリスク1つ(int *hoge = new int[5];)の場合
今回はその両辺にアスタリスクを追加した「int **g = new int*;」の意味についてご紹介します。
(1-1) 「int **g = new int*;」の意味
イメージとしては、右辺「new int*」(1要素の2次元配列)の先頭のアドレス(※注1)を、左辺の「g**」に格納する、といった感じです。
(※注1)上記の例は1要素なので「先頭アドレス」という表現は不適切かも知れませんが、「new int**[5]」のように複数要素の配列であれば、その先頭のアドレスを保持する、という意味です。
(図111)
gの値には「new int*」(1要素の2次元配列)の先頭要素のアドレスが入る
この状態から「*g = new int;」等により、g*もポインタとして配列のアドレスを格納して、ポインタのポインタ(≒2次元配列)が完成します。
(図112)
(1-2) サンプルで理解を深める
説明のみでは分かり辛いため、実際のサンプルプログラムも見ながら理解を深められたらと思います。また上記の規則はアスタリスク(*)がいくつ増えても同じなので、更に1つ増やした「int ***g = new int**;」(≒3次元配列)を例に見てみます。
●サンプルプログラム
(サンプル)
#include <iostream>
using namespace std;
int main(void){
int ***g = new int**;
*g = new int*;
**g = new int;
***g = 99;
cout << g << endl;
cout << *g << endl;
cout << **g << endl;
cout << ***g << endl;
cout << &g << endl;
cout << &*g << endl;
cout << &**g << endl;
cout << &***g << endl;
}
(図121)①
(実行結果)
コンパイル&実行した結果、各値(g、*g、**g、***g、&g、&*g、&**g、&***g)のアドレスが確認できます。
(図121)②
●サンプルプログラムの説明
・①「int ***g = new int**;」について
イメージとしては、右辺「new int**」(1要素の3次元配列)の先頭のアドレス(※注1)を、左辺の「g***」に格納する、といった感じです。
(※注1)上記の例は1要素なので「先頭アドレス」という表現は不適切かも知れませんが、「new int**[5]」のように複数要素の配列であれば、その先頭のアドレスを保持する、という意味です。
(図122)①
gの値には「new int**」(1要素の3次元配列)の先頭要素のアドレスが入る
上記の状態を、下記の簡単なプログラムで確認します。「int ***g = new int**;」の状態で(g、*g、&g、&*g、&**g)の値を確認しています。
(図122)②
「int ***g = new int**;」のみを書いて、各値を出力
各値の意味はそれぞれ次の通りです。
(表)
coutの対象 |
意味 |
g |
「g」の値 |
*g |
「g*」の値 |
&g |
「g」のアドレス |
&*g |
「g*」のアドレス=「g」の値 |
&**g |
「g**」のアドレス=「g*」の値 |
(図122)③coutで値を出力した結果
・②「*g = new int*;」について
この行では右辺「new int*」(1要素の2次元配列)の先頭要素のアドレスを、左辺の「*g」(gのポインタ)に格納するイメージです。
(図123)①
*gの値には「new int*」(1要素の2次元配列)の先頭要素のアドレスが入る
上記の状態を、下記の簡単なプログラムで確認し、その時の各値(g、*g、**g、&g、&*g、&**g、&***g)を確認しています。
(図123)②
各値の意味はそれぞれ次の通りです。
(表)
coutの対象 |
意味 |
g |
「g」の値 |
*g |
「g*」の値 |
**g |
「g**」の値 |
&g |
「g」のアドレス |
&*g |
「g*」のアドレス=「g」の値 |
&**g |
「g**」のアドレス=「g*」の値 |
&***g |
「g***」のアドレス=「g**」の値 |
・③「**g = new int;」について
この行では右辺「new int:」(1要素の1次元配列)の先頭要素のアドレスを、左辺の「**g」(gのポインタのポインタ)に格納するイメージです。
(図124)①
**gの値には「new int;」(1要素の1次元配列)の先頭要素のアドレスが入る
上記の状態を下記の簡単なプログラムで確認し、その時の各値(g、*g、**g、***g、&g、&*g、&**g、&***g)を確認しています。
(図124)②
各値の意味はそれぞれ次の通りです。
(表)
coutの対象 |
意味 |
g |
「g」の値 |
*g |
「g*」の値 |
**g |
「g**」の値 |
***g |
「g***」の値 |
&g |
「g」のアドレス |
&*g |
「g*」のアドレス=「g」の値 |
&**g |
「g**」のアドレス=「g*」の値 |
&***g |
「g***」のアドレス=「g**」の値 |
(図124)③coutで値を出力した結果