分配2d字符数组

Vla*_*adp 1 c++ memory arrays memory-management new-operator

构造函数

这是我分配它的方式:

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;
Run Code Online (Sandbox Code Playgroud)

在课堂上,它是:

char ***board;
Run Code Online (Sandbox Code Playgroud)

析构函数:

现在我想删除它,所以我写了这个(它是类字段的板):

for(i = 0; i < width; i++)
    delete (*board)[i];
delete (*board);
Run Code Online (Sandbox Code Playgroud)

运行时:

Board* b = new Board(16, 30, 99);
delete b;
Run Code Online (Sandbox Code Playgroud)

我得到一个未处理的异常.为什么?

Mar*_*tos 8

您正在存储指向堆栈上的变量的指针,一旦构造函数返回该变量就会变为无效.您应该将您的类的数据成员声明为char **board并分配this->board = board.

编辑:另见@Kerrek SB的评论.局部变量是多余的.只需直接使用数据成员(不含this->).

编辑2:矩形数组最好创建为单个数组,使用指针算法进行索引(这是编译器对声明的2D数组执行的操作):

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]; }
Run Code Online (Sandbox Code Playgroud)

这具有仅需要一个存储器分配(因此一个delete[])的优点.它还改善了缓存局部性,因为单元格是连续的.

更好的是,如果您在编译时知道维度,请使用模板:

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

这根本不需要内存分配(new Board当然除了).

  • 或者甚至只是从头开始使用`board`,没有局部变量.道德:任何时候你在C++中看到`***`,你做错了:-) (8认同)
  • @Vlad:我应该转过来问"你为什么要使用指针?" C++提供了多种类和习惯用法,几乎涵盖了你可能想要用指针做的所有事情,结果往往更健壮,更正确,更灵活. (2认同)