Сложности в понимание создания трёхмерных динамических структур в С++
Всех приветствую. Есть сложность в понимании задании многомерных динамических структур в C++. Если я правильно понимаю, то задать можно так(возьму в пример 3х мерную структуру):
vector<vector<vector<double>>> vector3d;
или видел такую запись:
using vector3d = vector<vector<vector<double>>>;
const vector3d& SECT;
Но честно говоря я не понимаю чем это отличается от
double ***vector3d;
Так же не понятно, нужно ли и как выделять память для этой ДИНАМИЧЕСКОЙ структуры до заполнения её.
Ответы (2 шт):
double ***vector3d; это указатель. И не факт что на трехмерный массив.
vector<vector<vector>> vector3d; это класс. Класс создан для удобного оперирования массивами. В нем реализованы методы для изменения размера и автоматического удаления памяти. Напрямую выделять память не нужно, но чтобы в нем появились элементы нужно делать ресайз(или иной метод вызвать схожий).
Разница же в методах в том, что ***vector3d это сишный вариант, его в плюсах лучше не использовать. Плюсы все же создавались чтобы вектор как класс создать.
Ещё стоит учесть, что в иногда сишные файлы компилируют как плюсовые, потому что так проще.
Вектор векторов v - это контейнер, содержащий контейнеры. Каждый контейнер типа vector надо заполнять отдельно, по умолчанию память не выделена. Ну и так как все вектора - независимые структуры, данные в них разбросаны где попало и у них может быть разный размер.
vector<vector<vector<double>>> v = {
{{0, 1, 2}}, // в 1м слое у нас 1 строка с 3 эл.
{{3, 4},{1}}, // в 2м слое у нас 2 строки с 2 и 1 эл.
{{3},{1,2},{4,5,6}},// в 3м слое у нас 3 строки
};
Указатель vector3d типа double *** может быть указателем на массив указателей double **, каждый из которых может является указателем на массив double *, а те - на массивы double. Но это также может быть указатель на первый элемент массива double ***. Выделяется память поочередно для каждого, в цикле. Как и у вектора векторов, все разбросано по памяти и разного размера, вот только сама структура размер не хранит!
Такую структуру иногда называют ragged array ("рваный" массив). В С++ в "голом" виде ее использовать не следует, а стоит описать класс, работающий с ним и хранящий размеры (тем самым выполнив S, O, I из SOLID).
Если же нужен монолитный 3х-мерный массив где все слои, столбцы и строки одинаковы, то лучше уж использовать одномерный массив или вектор. И завернуть все в класс с трехмерным индексом, примерно так (не проверялось):
#include <vector>
class Matrix {
public:
using DataType = double;
Matrix(const Matrix&) = default;
Matrix(Matrix&&) = default;
Matrix(int a, int b, int c): _a(a), _b(b), _c(c), _el(Matrix::init(a,b,c)){}
~Matrix() = default;
// Оператор индекса. В C++23 можно заменить на оператор
// operator[](int a, int b, int c)
DataType& operator()(int a, int b, int c) { return _el[_b*_c*a + _c*b + c]; }
// возвращает указатель на монолитный массив
DataType* data() { return _el.data(); }
private:
using Cont = std::vector<DataType >;
int _a, _b, _c;
Cont _el;
static Cont init(int a,int b,int c) {
Cont temp(a*b*c);
return temp;
}
};
int main()
{
Matrix v3d(3,3,3);
v3d(0,0,0) = 42;
v3d(2,2,1) = 34;
}