在 C++ 中使用二維指標動態配置記憶體時,配置方式的不同會直接影響記憶體的連續性,進而影響效能與存取方式。本文透過實測程式碼,深入分析兩種常見配置方法的記憶體佈局差異。
#include <cstdlib>
#include <iostream>
using namespace std;
#define nWidth 3
#define nHeight 4
int main() {
// 方法一:非連續配置
int **p = (int**)malloc(nWidth * sizeof(int*));
for (int j = 0; j < nWidth; j++) {
p[j] = (int*)malloc(nHeight * sizeof(int));
}
// 印出位址觀察連續性
for (int i = 0; i < nWidth; i++) {
for (int j = 0; j < nHeight; j++) {
printf("%p ", &p[i][j]);
}
cout << endl;
}
// 釋放記憶體
for (int j = 0; j < nWidth; j++) free(p[j]);
free(p);
// 方法二:連續配置
int **q = (int**)malloc(nWidth * sizeof(int*));
q[0] = (int*)malloc(nWidth * nHeight * sizeof(int));
for (int i = 1; i < nWidth; i++) {
q[i] = q[i-1] + nHeight; // 指向連續區塊的下一行起始位置
}
// 印出位址驗證連續性
for (int i = 0; i < nWidth; i++) {
for (int j = 0; j < nHeight; j++) {
printf("%p ", &q[i][j]);
}
cout << endl;
}
free(q[0]);
free(q);
return 0;
}

先配置指標陣列 p,再為每一列獨立呼叫 malloc。每列內部連續(相鄰元素間隔 4 bytes),但列與列之間在記憶體中位置隨機分散。適用於列數不固定或需動態調整列大小的情境。
先配置指標陣列 q,再於 q[0] 一次配置所有所需空間(nWidth * nHeight * sizeof(int)),接著透過指標運算讓 q[i] 指向連續區塊中對應行的起始位置。整個二維陣列在記憶體中呈現完全連續分佈,優於快取命中率,適合效能敏感場合。
free(p[j]),最後 free(p)。free(q[0]) 釋放資料區塊,再 free(q) 釋放指標陣列。實務開發建議使用 std::vector<std::vector<int>> 或單維 std::vector<int> 配合索引運算 idx = i * nHeight + j,避免手動管理記憶體風險。若需高效能連續配置,可考慮 std::unique_ptr<int[]> 搭配自定義刪除器。