Всегда лучше хранить массивы как простые одномерные массивы и фиксировать способ доступа к ним. Ваш mat[5][2][1]
эквивалентен mat[1 + 2*2 + 5*10]
. При переходе к динамическому выделению памяти c создание массива с индексом mat[5][2][1]
подразумевает выделение массива указателей на массивы указателей на массивы данных. Это приводит к огромным накладным расходам на выделение памяти (что довольно дорого) и вызывает фрагментацию памяти и низкую производительность кэша. Вместо этого выделение одного простого массива, который может содержать данные, и вычисление линейного индекса из ваших трех индексов довольно просто и дешево.
Это тривиальная реализация (без какой-либо формы проверки) для динамически распределенного 3D массив:
struct Mat {
using value_type = int32_t;
std::vector<value_type> data;
int size[3] = {0, 0, 0};
Mat(int s1, int s2, int s3) {
size[0] = s1; size[1] = s2; size[2] = s3;
data.resize(s1 * s2 * s3);
}
value_type operator()(int i, int j, int k) {
return data[(k * size[1] + j) * size[0] + i];
}
};
Конечно, вы можете превратить его в class
с соответствующим сокрытием данных и т. Д. c. Или вы можете просто использовать одну из множества существующих библиотек, которые реализуют такие массивы. Для индексации есть перегруженный оператор ()
: m(5,2,1)
преобразуется в соответствующую индексацию в массив 1D m.data
. (Я не стал возвращать индексированный элемент по ссылке, но это, конечно, имело бы больше смысла).
Вот полная программа для его тестирования. С входными данными, являющимися целыми числами 1:90 в порядке хранения основных столбцов, в MATLAB я вижу это:
>> mat(6,3,2)
ans = 69
Программа C ++ выводит это:
m(5,2,1) = 69
Исходный код:
#include <vector>
#include <fstream>
#include <iostream>
struct Mat {
using value_type = int32_t;
std::vector<value_type> data;
int size[3] = {0, 0, 0};
Mat(int s1, int s2, int s3) {
size[0] = s1; size[1] = s2; size[2] = s3;
data.resize(s1 * s2 * s3);
}
value_type operator()(int i, int j, int k) {
return data[(k * size[1] + j) * size[0] + i];
}
};
int main() {
std::ifstream input("mat.bin");
Mat m(9, 5, 2);
input.read(reinterpret_cast<char*>(m.data.data()), m.data.size() * sizeof(Mat::value_type));
input.close();
std::cout << "m(5,2,1) = " << m(5,2,1) << '\n';
}