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

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

関連記事

C++における「>>」の意味について

  <目次> (1) C++における「>>」の意味について  (1-1) 概要  (1-2) サンプルプログラム  (1-3) どんな時に使われる?⇒データ圧縮  (1-4) 備 …

GDBの使い方をC++のプログラムのデバッグを例にご紹介

  <目次> (1) GDBの使い方をC++のプログラムのデバッグを例にご紹介  (1-1) GDBのデバッグのシナリオ概要(例)  (1-2) GDBのデバッグ手順(例)  (1-3) そ …

Valgrindの使い方や見方について(基礎編)

  <目次> (1) Valgrindの使い方や見方について(基礎編)  (1-1) メモリリークのチェックのやり方  (1-2) 「valgrind」コマンドの基本的な使い方  (1-3) …

C++のfork関数の構文や使い方について

  <目次> (1) C++のfork関数の構文や使い方について  (1-1) fork()関数とは?概要や目的  (1-2) fork()関数の構文  (1-3) fork()関数のサンプ …

no image

C++で「error: cannot initialize a variable of type ‘const unsigned char’ with an lvalue of type ‘const char [x]’」が発生した時の原因と対処

<目次> (1) C++で「error: cannot initialize a variable of type ‘const unsigned char’ with an …

  • English (United States)
  • 日本語
Top