如何使用智能指针声明二维及以上维度的数组?
我来帮你梳理下如何用智能指针实现二维和三维数组,先从基础用法回顾开始,再给出具体的实现方案:
用智能指针实现二维/三维数组的方法
首先先回顾下单个变量和一维数组的智能指针声明方式:
unique_ptr<int> ptr1(new int {}); unique_ptr<int[]> ptr2(new int[5] {});
单个变量和一维数组可以按上述方式声明。那如何用智能指针实现二维或更高维度的数组呢?
先看原生指针实现二维、三维数组的示例:
const size_t idx = 5; // 2D int** ptr3 = new int*[idx]{}; for (size_t i = 0; i < idx; i++) { ptr3[i] = new int[idx]{}; } // 释放内存 for (size_t i = 0; i < idx; i++) { delete[] ptr3[i]; } delete[] ptr3; // 3D int*** ptr4 = new int**[idx]{}; for (size_t i = 0; i < idx; i++) { ptr4[i] = new int*[idx]{}; for (size_t j = 0; j < idx; j++) { ptr4[i][j] = new int[idx]{}; } } // ... 释放代码省略 ...
接下来给出对应的智能指针实现版本:
二维数组的智能指针实现
有两种常用方案,你可以根据场景选择:
方案1:嵌套unique_ptr模拟原生指针结构
这种方式和原生指针的逻辑完全对应,不需要改变访问习惯:
const size_t idx = 5; // 二维数组:嵌套的unique_ptr unique_ptr<unique_ptr<int[]>[]> ptr3(new unique_ptr<int[]>[idx]); for (size_t i = 0; i < idx; ++i) { ptr3[i] = make_unique<int[]>(idx); // 用make_unique更安全简洁 } // 不需要手动释放内存,unique_ptr会自动递归回收所有层级的内存
方案2:连续内存块实现(推荐)
把二维数组当成一维连续内存来管理,内存更紧凑、缓存友好,适合固定大小的数组:
const size_t idx = 5; // 连续内存版二维数组 unique_ptr<int[]> ptr3_flat(new int[idx * idx]); // 访问方式:ptr3_flat[i * idx + j] 等价于原生指针的 ptr3[i][j]
三维数组的智能指针实现
同样有两种对应方案:
方案1:嵌套unique_ptr
和三维原生指针结构对应,语法稍繁琐但逻辑直观:
const size_t idx = 5; unique_ptr<unique_ptr<unique_ptr<int[]>[]>[]> ptr4(new unique_ptr<unique_ptr<int[]>[]>[idx]); for (size_t i = 0; i < idx; ++i) { ptr4[i] = make_unique<unique_ptr<int[]>[]>(idx); for (size_t j = 0; j < idx; ++j) { ptr4[i][j] = make_unique<int[]>(idx); } } // 同样无需手动释放,智能指针自动处理所有内存回收
方案2:连续内存块实现
把三维数组转为一维连续内存,性能更优:
const size_t idx = 5; unique_ptr<int[]> ptr4_flat(new int[idx * idx * idx]); // 访问方式:ptr4_flat[i * idx * idx + j * idx + k] 等价于原生指针的 ptr4[i][j][k]
额外说明
- 优先推荐连续内存版,嵌套指针的方式会分散内存,影响缓存命中率,而连续内存的管理更简单、性能更好。
- 尽量使用
make_unique代替直接new,它能避免潜在的内存泄漏风险,代码也更简洁。 - 如果是动态调整维度的场景,嵌套
unique_ptr可以灵活适配,但要注意它的语法复杂度。
内容的提问来源于stack exchange,提问作者user3818260
相关产品推荐
相关产品推荐

