C++のdelete[]はどうやって配列のサイズを「認識」しているのか?仕組みを解説
C++における動的メモリ管理では、new演算子がヒープメモリ上にオブジェクトや配列を確保し、delete/delete[]演算子がそのメモリを解放します。ここでよく疑問に挙がるのが、「delete[]は引数としてポインタしか受け取っていないのに、なぜ配列の要素数(サイズ)を正しく把握できるのか?」という点です。
delete[]がサイズを認識できる仕組み
答えはシンプルで、new[]演算子が確保時に要素数をどこかに記録しており、delete[]はその記録を参照してメモリを解放するからです。
具体的には、多くのコンパイラ実装では、new int[n]のように配列を確保するとき、ユーザーが要求した領域に加えて、要素数を格納するための隠しヘッダー領域(俗に「クッキー」と呼ばれます)が先頭に追加して確保されます。
new[]:確保した要素数をこの隠しヘッダーに書き込み、実際のデータ領域の先頭アドレスを返すdelete[]:渡されたポインタの手前にあるヘッダーを読み取り、そこから要素数を取得する- 取得した要素数をもとに、各要素のデストラクタを呼び出し、ヘッダーを含む全体のメモリブロックを解放する
この仕組みがあるため、プログラマが明示的にサイズを渡さなくても、delete[]は正しくメモリを解放できます。
注意: new[]で確保したメモリは必ずdelete[]で、単一オブジェクトのnewで確保したメモリはdeleteで解放してください。これらを混在させると未定義動作になります。
サンプルコード:2次元配列の動的確保と解放
以下は、new[]で2次元配列を動的に確保し、delete[]で解放する典型的な例です。
#include <iostream>
using namespace std;
int main() {
int B = 4; // 行数
int A = 5; // 列数
// ポインタ配列を確保
int** a = new int*[B];
for(int i = 0; i < B; ++i)
a[i] = new int[A];
// 値を代入
for(int i = 0; i < B; ++i)
for(int j = 0; j < A; ++j)
a[i][j] = i;
// 結果を出力
for(int i = 0; i < B; ++i)
for(int j = 0; j < A; ++j)
cout << a[i][j] << "\n";
// メモリを解放(各行 → 配列本体の順に)
for(int i = 0; i < B; ++i)
delete [] a[i];
delete [] a;
return 0;
}
出力結果
0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3
ポイントまとめ
new[]は確保時に要素数を内部に記録するため、delete[]はサイズ情報を引数なしで取得できる- 解放時は、まず各行(内側の配列)を
delete[]で解放し、その後に外側のポインタ配列を解放するのが正しい手順 - 現代のC++では、
std::vectorやstd::unique_ptr<int[]>などのスマートポインタを使うことで、こうした手動の確保・解放ミスを防げます
-
OpenCVとC++を使った色追跡の実装方法:HSV変換から軌跡の描画まで
色追跡(カラートラッキング)は、色検出とよく似た画像処理です。追跡を実現するには、検出したオブジェクトの面積を計算し、その領域の現在位置を求める処理を数行追加します。最後に、OpenCVのline()関数を使って、オブジェクトが移動した軌跡を線として描画します。 この記事では、トラックバーでHSVのしきい値をリアルタイムに調整しながら、Webカメラの映像から特定色のオブジェクトを検出し、その動きを追跡する方法を解説します。 色追跡の基本的な流れ 映像の取得:VideoCaptureクラスでWebカメラからフレームを取得します。 HSVへの変換:cvtColor()関数でBGR画像をHSV形
-
C++のnew演算子を使って2次元配列を動的に宣言・生成する方法
動的な2次元配列とは、基本的に「配列へのポインタ」を要素とする配列(ポインタの配列)のことです。つまり、各行が独立した1次元配列としてヒープ上に確保され、それらの先頭アドレスを格納するポインタ配列によって全体が管理されます。下図は、3×4の2次元配列のイメージです。アルゴリズムC++のnew演算子で2次元配列を動的に確保する手順は以下の通りです。Begin 配列の寸法(行数・列数)を宣言する。 new を使って 2次元配列 a[][] を動的に確保する。 配列に要素を代入する。 配列の内容を出力する。 delete でメモリを解放する。 Endサンプルコ