Rainbow Engine

IT技術を分かりやすく簡潔にまとめることによる学習の効率化、また日常の気付きを記録に残すことを目指します。

C++

C++の「int **g = new int*;」の意味について

投稿日:2021年10月24日 更新日:

 

<目次>

(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で値を出力した結果

 

Adsense審査用広告コード


Adsense審査用広告コード


-C++

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

パイプ通信とは?概要やサンプルプログラムをご紹介

  <目次> (1) パイプ通信とは?概要やサンプルプログラムをご紹介  (1-1) パイプ通信の概要  (1-2) パイプ通信の構文  (1-3) パイプ通信のサンプルプログラム①(単一プ …

C++の値渡しと参照渡しの使い分けや違いについて

<目次> (1) C++の値渡しと参照渡しの使い分けや違いについて  (1-1) 「値渡し」とは?  (1-2) 「参照渡し」とは?  (1-3) 「値渡し」と「参照渡し」の使い分け (1) C++の …

C++の「::」の記載の意味について

  <目次> (1) C++の「::」の記載の意味について  (1-1) 「::」の意味は?  (1-2) サンプル①:スコープ演算子「::」を使ってグローバル変数にアクセス  (1-3) …

C++の「->」(アロー演算子)とは?意味や使い方をご紹介

  <目次> (1) C++の「->」(アロー演算子)とは?意味や使い方をご紹介  (1-1) C++の「->」(アロー演算子=arrow operator)とは?  (1-2) …

C++のlocaltime関数がスレッドアンセーフである理由と使用上の注意点

  <目次> (1) C++のlocaltime関数がスレッドアンセーフである理由と使用上の注意点  (1-1) localtime関数がスレッドアンセーフである理由  (1-2) loca …

  • English (United States)
  • 日本語
Top