はじめに
C++で変数を宣言すると、通常、その変数は関数が終了すると同時にメモリ上から消滅します。しかし、プログラムの実行中に「必要な時に必要な分だけ、メモリを確保したい」という場面があります。
このような、プログラムの実行時(ランタイム)にメモリを確保することを「動的なメモリ確保」と呼びます。動的に確保したメモリは、そのポインタを介してアクセスし、使い終わったら明示的に解放する必要があります。
この記事では、new
演算子で動的にメモリを確保し、delete
演算子でそれを解放するという、C++における動的メモリ確保の基本を解説します。
動的なメモリ確保のサンプルコード
このコードは、new
演算子を使ってint
型の変数を格納するためのメモリを動的に確保し、そのメモリに値を代入した後、delete
演算子でメモリを解放する一連の流れを示します。
完成コード
#include <iostream>
using namespace std;
int main() {
// 1. 動的に確保したメモリを指すためのポインタを宣言
int* pDynamicInt;
// 2. new演算子で、int型1つ分のメモリを動的に確保
pDynamicInt = new int;
cout << "int型1つ分のメモリを動的に確保しました。" << endl;
// 3. 確保したメモリに、ポインタ経由で値を代入
*pDynamicInt = 100;
cout << "確保したメモリを使って、値「" << *pDynamicInt << "」を出力します。" << endl;
// 4. delete演算子で、確保したメモリを解放
delete pDynamicInt;
cout << "確保したメモリを解放しました。" << endl;
// NG: 解放後のポインタにアクセスしようとすると、未定義の動作を引き起こす
// cout << *pDynamicInt << endl;
return 0;
}
実行結果
int型1つ分のメモリを動的に確保しました。
確保したメモリを使って、値「100」を出力します。
確保したメモリを解放しました。
コードの解説
1. pDynamicInt = new int;
new int
:new
演算子が、int
型1つ分のメモリ領域をヒープ(動的メモリ領域)に確保します。- 戻り値: 確保に成功すると、そのメモリ領域の先頭アドレスを返します。
pDynamicInt = ...
: 確保したメモリのアドレスを、int*
型のポインタpDynamicInt
に代入しています。
2. *pDynamicInt = 100;
ポインタ pDynamicInt
が指し示す先(メモリ領域そのもの)にアクセスするには、アスタリスク *
を使った間接参照を行います。これにより、確保したメモリに 100
という値を書き込んでいます。
3. delete pDynamicInt;
これが、動的に確保したメモリを解放するための重要な命令です。
delete
演算子は、new
で確保したメモリをシステムに返却し、再利用可能な状態にします。new
で確保したメモリは、delete
を使わない限り、プログラムが終了するまで自動では解放されません。これにより、プログラムの実行中にメモリが徐々に減っていく「メモリリーク」という問題が発生します。
delete
を実行すると、ポインタ pDynamicInt
は無効なアドレスを指す状態になります。このポインタを「ダングリングポインタ」と呼びます。
まとめ
今回は、C++の動的なメモリ確保と解放の基本について解説しました。
new
でメモリを確保し、そのアドレスをポインタで受け取る。delete
で、不要になったメモリを明示的に解放する。new
とdelete
は必ず対で使う。
動的なメモリ確保は、配列のサイズをプログラムの実行中に変更したい場合など、柔軟なデータ管理を行う上で必須のテクニックです。メモリリークという問題が伴うため、new
を使ったら delete
する、というルールを徹底しましょう。