Вопрос о двумерном массиве c ++ - PullRequest
1 голос
/ 29 апреля 2011

Я хотел бы создать что-то вроде указателя на двумерный массив указателей (с шириной и высотой x).
Будет ли этот код делать то, что я ожидаю? (Создайте элементы массива, записав некоторую информацию о них, затем освободите всю выделенную память.)

int main(int argc, char** argv) {
    int x = 3;
    Node ***array = new Node**[x];
    for (int i = 0; i < 3; i++) {
        array[i] = new Node*[x];
        for (int j = 0; j < x; j++) {
            array[i][j] = new Node(i, j); /* Node::Node(int row, int col) */
        }
    }
    /* ....... */
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < x; j++) {
            cout << array[i][j]->row << ", " << array[i][j]->col << endl;
        }
    }
    /* ....... */
    for (int i = 0; i < x; i++) {
        for (int j = 0; j < x; j++) {
            delete array[i][j];
            //array[i][j] = NULL;
        }
        delete[] array[i];
        //array[i] = NULL;
    }
    delete[] array;
    //array = NULL;
    return 0;
}

Или я должен создать vector из vector указателей на Node объектов?
Или же я должен разместить свои объекты в стеке?

(я использую указатели, потому что в Java или C # вы всегда должны использовать ключевое слово new при создании объекта (однако я не думаю, что все объекты находятся в куче памяти), и я прочитайте, что в куче больше свободного места.)

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

Ответы [ 3 ]

4 голосов
/ 29 апреля 2011

Я рекомендую вам использовать vector< vector<Node> >, boost :: multi_array , или вы можете свернуть свой собственный класс динамического двумерного массива (это не так сложно), который является оберткой вокруг плоского 1D std::vector.

Все вышеперечисленные решения сохранят ваши объекты Node в куче и позаботятся об очистке памяти.

Вот пример простого класса Matrix, который является оболочкой std::vector<T>:

#include <iostream>
#include <vector>

template <class T>
class Matrix
{
public:
    Matrix() : width_(0), height_(0), vec_(0) {}

    Matrix(size_t width, size_t height)
        : width_(width), height_(height), vec_(width*height) {}

    size_t size() const {return vec_.size();}

    size_t width() const {return width_;}

    size_t height() const {return height_;}

    // Clears all preexisting data
    void resize(size_t width, size_t height)
        {width_ = 0; height_ = 0; vec_.clear(); vec_.resize(width*height);}

    void clear() {width_ = 0; height_ = 0; vec_.clear();}

    T& operator()(size_t col, size_t row) {return vec_[row*width_ + col];}

    const T& operator()(size_t col, size_t row) const
        {return vec_[row*width_ + col];}

private:
    size_t width_;
    size_t height_;
    std::vector<T> vec_;
};

int main()
{
    Matrix<double> a(3, 4);
    a(1, 2) = 3.1415;
    std::cout << a(1,2) << "\n";
}

Он использует operator() для имитации синтаксиса array[2][4] многомерных массивов в стиле c. Вам не нужно беспокоиться о мелких копиях, освобождении памяти и т. Д., Поскольку vector уже позаботится об этом.

0 голосов
/ 29 апреля 2011

Ваш код выглядит правильно, но я бы рекомендовал создать вектор векторов Node объектов Класс vector управляет собственной памятью, поэтому вам не нужно беспокоиться о том, чтобы забыть о delete что-либо.

Вам даже не нужно указывать вектор векторов из Node указателей. Если вы скажете my_vector.push_back(my_node), он скопирует my_node в память, выделенную для кучи вектора. Если вы возвращаете вектор из своей функции, узел идет с ним (он не теряется в конце функции, как объект, размещенный в стеке). Например:

// declare a vector of nodes on the stack
vector<node> nodes;

// declare a Node object on the stack
Node my_node(/*arguments*/);

// copy my_node (on the stack) into the vector's memory (on the heap)
nodes.push_back(my_node);

// (return 'nodes' from this function and store it somewhere)

Обратите внимание, что узел в nodes отличается от объекта my_node. Если вместо этого вы сделали my_node с new, push_back() скопирует указатель (а не сам объект), и объект в векторе будет тем же, который вы создали с помощью new. Если вы сделаете это, у вас есть объект, и вы должны помнить, чтобы удалить его, когда вы закончите. Если вы позволите вектору владеть объектом (как в моем примере кода), он справится с этим за вас.

0 голосов
/ 29 апреля 2011

Рассматривали ли вы использование Boost.Multidimensional.Array?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...