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 шт):

Автор решения: Swift - Friday Pie

В таких случаях нужен динамический контейнер, т.е. тот,что может выделять память во время исполнения программы. Все зависит от того что дальше с этой "матрицей" надо делать.

Для ряда задач вектор вложенный в вектор будет неэффективным. Во-первых , занимаемая память не будет непрерывной областью - каждый подвектор-строка выделяет собственную область. Во-вторых, изменение длины вектора,добавление элементов, может быть дорогой операцией, пропорциональной длине вектора.

В ряде случаев можно выделить память заранее и тем самым исключить затраты на перевыделение. В других случаях нужно использовать что-то другое. Например, двумерную матрицу размер которой далее не меняется можно представить как одномерный вектор, т.к. изменяемые в размере матрицы - вещь в практике специфическая. Ну, и раз пишем на Си++, удобно обернуть в свой класс, например:

#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().

→ Ссылка