C++ 動的メモリ


C++ で動的メモリがどのように機能するかを理解することは、資格のある C++ プログラマーになるために不可欠です。 C++ プログラムのメモリは 2 つの部分に分割されます:

  • スタック: 関数内で宣言されたすべての変数はスタック メモリを占有します。

  • ヒープ: これはプログラム内の未使用のメモリであり、プログラムの実行中にメモリを動的に割り当てるために使用できます。

多くの場合、定義された変数に特定の情報を格納するために必要なメモリの量を事前に予測することはできません。必要なメモリのサイズは実行時に決定する必要があります。

C++ では、特別な演算子を使用して、実行時に特定の型の変数にヒープ内のメモリを割り当てることができます。これにより、割り当てられた領域のアドレスが返されます。この演算子は new 演算子です。

メモリを動的に割り当てる必要がない場合は、delete 演算子を使用して、new 演算子によって以前に割り当てられたメモリを削除できます。

new 演算子と delete 演算子

以下は、new 演算子を使用して任意のデータ型に動的にメモリを割り当てるための一般的な構文です:

new data-type;

ここで、data-type は配列を含む任意の組み込みデータにすることができます。クラスや構造体を含む任意のユーザー定義のデータ型です。まず、組み込みのデータ型を見てみましょう。たとえば、double 型へのポインタを定義してから、実行時に割り当てられるメモリを要求できます。これは、次のように new 演算子を使用して実現できます:

double* pvalue  = NULL; // 初始化为 null 的指针
pvalue  = new double;   // 为变量请求内存

空きストレージ領域が使い果たされている場合、メモリの割り当てが成功しない可能性があります。したがって、新しい演算子が NULL ポインターを返すかどうかを確認し、次の適切なアクションを実行することをお勧めします:

double* pvalue  = NULL;
if( !(pvalue  = new double ))
{
   cout << "Error: out of memory." <<endl;
   exit(1);

}

malloc() この関数は C 言語で登場し、C++ にもまだ存在しますが、使用しないことをお勧めします。可能な限り malloc() 関数を使用してください。 malloc() 関数と比較した new の主な利点は、new がメモリを割り当てるだけでなく、オブジェクトも作成することです。

動的にメモリが割り当てられた変数がもう必要ないと感じたときはいつでも、以下に示すように、delete 演算子を使用して変数が占有しているメモリを解放できます:

delete pvalue;        // 释放 pvalue 所指向的内存

上記は次の中で使用されます。 new 演算子と delete 演算子の使用方法を示す概念例:

#include <iostream>
using namespace std;

int main ()
{
   double* pvalue  = NULL; // 初始化为 null 的指针
   pvalue  = new double;   // 为变量请求内存
 
   *pvalue = 29494.99;     // 在分配的地址存储值
   cout << "Value of pvalue : " << *pvalue << endl;

   delete pvalue;         // 释放内存

   return 0;
}

上記のコードをコンパイルして実行すると、次の結果が生成されます:

Value of pvalue : 29495

配列の動的メモリ割り当て

文字配列 ( 20 文字の文字列) を使用してメモリを割り当てるには、上記の例の構文を使用して、次のように配列にメモリを動的に割り当てることができます:

char* pvalue  = NULL;   // 初始化为 null 的指针
pvalue  = new char[20]; // 为变量请求内存

作成したばかりの配列を削除するには、ステートメントは次のとおりです:

delete [] pvalue;        // 删除 pvalue 所指向的数组

以下は、次のように多次元配列にメモリを割り当てることができる new 演算子の一般的な構文です:

int ROW = 2;
int COL = 3;
double **pvalue  = new double* [ROW]; // 为行分配内存

// 为列分配内存
for(int i = 0; i < COL; i++) {
    pvalue[i] = new double[COL];
}

多次元配列のメモリを解放します:

for(int i = 0; i < COL; i++) {
    delete[] pvalue[i];
}
delete [] pvalue;

オブジェクトの動的メモリ割り当て

オブジェクトは単純なデータと何ら変わりません種類。たとえば、以下のコードを見てください。この概念を明確にするためにオブジェクトの配列を使用します。

#include <iostream>
using namespace std;

class Box
{
   public:
      Box() { 
         cout << "调用构造函数!" <<endl; 
      }
      ~Box() { 
         cout << "调用析构函数!" <<endl; 
      }
};

int main( )
{
   Box* myBoxArray = new Box[4];

   delete [] myBoxArray; // Delete array

   return 0;
}

4 つの Box オブジェクトを含む配列にメモリを割り当てたい場合、コンストラクターは 4 回呼び出されます。同様に、オブジェクトが削除されると、デストラクターも同じ回数 (4 回) 呼び出されます。

上記のコードをコンパイルして実行すると、次の結果が生成されます:

调用构造函数!
调用构造函数!
调用构造函数!
调用构造函数!
调用析构函数!
调用析构函数!
调用析构函数!
调用析构函数!