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

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

関連記事

Base64とは?概要やアルゴリズムについてご紹介

  <目次> (1) Base64とは?概要やアルゴリズムについてご紹介  (1-1) Base64とは?  (1-2) Base64の仕組み  (1-3) Base64の実装 (1) Ba …

Valgrindとは?使い方や概要をご紹介(メモリリーク検知ツール)

  <目次> (1) Valgrindとは?使い方や概要をご紹介(メモリリーク検知ツール)  (1-1) Valgrindとは?  (1-2) Valgrindの導入方法  (1-3) Va …

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

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

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

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

ValgrindのPossibly Lostの意味や実際のサンプルをご紹介

  <目次> (1) ValgrindのPossibly Lostの意味や実際のサンプルをご紹介  (1-1) Valgrindの「Possibly Lost」はどんな状況?  (1-2) …

  • English (United States)
  • 日本語
Top