Выделение 2d массива символов - PullRequest
1 голос
/ 19 сентября 2011

Конструктор

Вот как я это выделяю:

char **board = new char*[width];
for(i = 0; i < width; i++){
    board[i] = new char[height];
    for(j = 0; j < height; j++)
        board[i][j] = 0;
}
this->board = &board;

Внутри класса это:

char ***board;

Destructor:

Теперь я хочу удалить его, поэтому я написал это (доска это поле класса):

for(i = 0; i < width; i++)
    delete (*board)[i];
delete (*board);

При запуске этого:

Board* b = new Board(16, 30, 99);
delete b;

Я получил необработанное исключение. Почему?

Ответы [ 3 ]

8 голосов
/ 19 сентября 2011

Вы храните указатель на переменную в стеке, которая становится недействительной, как только возвращается конструктор. Вы должны объявить член данных вашего класса как char **board и назначить this->board = board.

РЕДАКТИРОВАТЬ: См. Также комментарий @Kerrek SB. Локальная переменная является избыточной. Просто используйте элемент данных напрямую (без this->).

РЕДАКТИРОВАНИЕ 2: Прямоугольные массивы лучше всего создавать в виде одного массива, используя арифметику указателей для индексации (что в любом случае делает компилятор с объявленными двумерными массивами):

char *board;
...
board = new char[width*height];
for(i = 0; i < width*height; ++i){
    board[i] = 0;
}
...
char& operator()(int i, int j) { return board[width*i + j]; }

Это имеет преимущество в том, что требуется только одно выделение памяти (и, следовательно, один delete[]). Это также улучшает локальность кэша, поскольку ячейки являются смежными.

Еще лучше, если вы знаете размеры во время компиляции, используйте шаблоны:

template <int W, int H>
class Board {
    char board[W][H];
    ...
};
...
Board<8, 8>* b = new Board<8, 8>(...);

Это вообще не требует выделения памяти (кроме new Board, конечно).

3 голосов
/ 19 сентября 2011

Все, что вам new нужно delete, точно так же:

board = new char*[width];
...
board[i] = new char[height];
...
...
delete[] board[i];
delete[] board;

В этом случае разыменование не требуется.

1 голос
/ 19 сентября 2011

Вы должны использовать возможности C ++.

class Board
{
    std::vector<std::vector<char>> board;

public:
    Board(std::vector<std::vector<char>> const& board) : board(board) {}

    Board(size_t x, size_t y, char val = 0)
    {
        std::vector<char> x2(x, val);
        this->board(y, x2);
    }
};

Все, что вам нужно сделать сейчас, это board[y].push_back(char_x_val), чтобы добавить новый элемент в конец. Вы можете обращаться с board[y][x] точно так же, как с любым другим 2D-массивом (ну, почти), но не беспокойтесь об освобождении.

Подробнее о векторах здесь . (Кто-нибудь знает хороший учебник?)

...