推荐用std::vector扁平化存储+维度元数据实现多维数组,支持任意维度、行优先索引、边界检查、reshape原地调整及强异常安全。

用现代 C++ 实现一个可变大小的多维数组,推荐基于 std::vector 构建,兼顾安全性、灵活性和易用性。核心思路是用一维连续存储 + 维度信息 + 索引映射,避免嵌套 vector 带来的内存碎片和性能开销。
设计关键:扁平化存储 + 维度元数据
不使用 vector<vector>></vector>,而是将所有元素线性存于单个 std::vector<t></t> 中,同时保存各维度大小(如 {dim0, dim1, dim2})和总尺寸。访问时通过多维下标计算一维偏移量。
- 支持任意维度(编译期或运行期确定),常见场景建议用
std::vector<size_t></size_t>存储 shape - 索引计算采用行优先(C-style):对于 shape
[D0,D1,D2],(i,j,k)对应位置为i*D1*D2 + j*D2 + k - 构造时检查维度乘积是否溢出
size_t,并预留空间避免多次重分配
基础接口:构造、访问与形状管理
提供类似 std::array 或 NumPy 的简洁语法,例如 Array<double> a({2,3,4});</double> 或运行时维度 Array<double> a({5,6,7,2});</double>。
- 重载
operator[]返回代理对象(proxy),支持链式调用如a[i][j][k];也可提供at()做边界检查 -
shape()返回const std::vector<size_t>&</size_t>,size()返回总元素数,ndim()返回维度数 - 允许 reshape:只要新旧 shape 元素总数一致,就原地调整维度信息,不拷贝数据
内存与异常安全细节
构造失败(如维度非法或内存不足)时确保强异常安全:要么完全成功,要么不修改对象状态。
- 在构造函数中先验证 shape 合法性(每个维度 ≥ 1,总 size 不溢出),再调用
data_.reserve(total_size) - 使用
std::vector<t></t>自动管理内存,析构时释放,无需手动new/delete - 对非常量访问返回引用,常量访问返回 const 引用;proxy 类内部只存指针和当前维度偏移,轻量无拷贝
示例:三维数组的简易实现片段
以下为简化版核心逻辑(省略 proxy 和模板特化):
template<typename T>
class Array {
std::vector<T> data_;
std::vector<size_t> shape_;
std::vector<size_t> strides_; // 可选:预计算每维步长,加速索引
<pre class="brush:php;toolbar:false;">size_t index(const std::vector<size_t>& idx) const {
size_t pos = 0;
for (size_t d = 0; d < idx.size(); ++d) {
if (idx[d] >= shape_[d]) throw std::out_of_range("Index out of bounds");
pos = pos * shape_[d] + idx[d];
}
return pos;
}public:
Array(const std::vector
T& operator()(size_t i, size_t j, size_t k) {
return data_[i * shape_[1] * shape_[2] + j * shape_[2] + k];
}};

















