2-х мерный массив с размером переменной C++
Всем привет! Я писал код на С++ и столкнулся с проблемой после считывания данных с файла типа .conf, а именно, я хотел создать 2-х мерный массив со считанным размером. Так я уже пытался создать: // N,M - я считал с файла. Тип данных у них int, но size_t я тоже пробовал
double array[N][M]; //код ошибки: "Variable length arrays are a C99 feature"
std::array<std::array<double,N>,M> array; //код ошибки: "Non-type template argument is not a constant expression"`
Последние что я пробовал было:
std::vector<std::vector<double>> array;
И такой способ работает, но он очень медленный...
Может кто-нибудь, пожалуйста, помочь и подсказать, что тут лучше было бы использовать?
Ответы (1 шт):
В таких случаях нужен динамический контейнер, т.е. тот,что может выделять память во время исполнения программы. Все зависит от того что дальше с этой "матрицей" надо делать.
Для ряда задач вектор вложенный в вектор будет неэффективным. Во-первых , занимаемая память не будет непрерывной областью - каждый подвектор-строка выделяет собственную область. Во-вторых, изменение длины вектора,добавление элементов, может быть дорогой операцией, пропорциональной длине вектора.
В ряде случаев можно выделить память заранее и тем самым исключить затраты на перевыделение. В других случаях нужно использовать что-то другое. Например, двумерную матрицу размер которой далее не меняется можно представить как одномерный вектор, т.к. изменяемые в размере матрицы - вещь в практике специфическая. Ну, и раз пишем на Си++, удобно обернуть в свой класс, например:
#include <iostream>
#include <vector>
#include <stdexcept>
class matrix {
int M = 2,
N = 2; // по умолчанию - 2 на 2? :)
std::vector<double> m = std::vector<double>(M*N);
public:
matrix(int rows, int cols) : M(rows), N(cols) {}
// При использовании старых стандартов придется написать так
//matrix(int rows, int cols) : M(rows), N(cols), m(std::vector<double>(rows*cols)) {}
// операторы доступа к одному элементу
double& operator() (int row, int col) {
if(row >= M || col >= N) throw std::out_of_range("Matrix index out of range");
return m[row*col + col];
}
double operator() (int row, int col) const {
if(row >= M || col >= N) throw std::out_of_range("Matrix index out of range");
return m[row*col + col];
}
// прочие методы
};
int main()
{
int r = 3, c = 5;
matrix M(r,c);
M(1,1) = 3.14;
std::cout << M(1,1) << std::endl;
}
Конечно же можно добавить методы сериализации из потока и копирования данных напрямую, какую-то обертку для итераторов, по надобности, чтобы не дергать все элементы через operator().