【问题标题】:Allocating 2d array of chars分配二维字符数组
【发布时间】:2011-09-18 22:07:20
【问题描述】:

构造函数

这就是我分配它的方式:

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;

析构函数:

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

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

运行时:

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

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

【问题讨论】:

  • 进入析构函数时捕获到未处理的异常
  • delete 都应该是 delete[]
  • 你有什么理由不只是使用std:vector&lt;std::string&gt;(width)

标签: c++ arrays memory memory-management new-operator


【解决方案1】:

您正在堆栈上存储一个指向变量的指针,该指针在构造函数返回后立即变为无效。您应该将您的类的数据成员声明为char **board 并分配this-&gt;board = board

编辑: 另见@Kerrek SB 的评论。局部变量是多余的。直接使用数据成员即可(不用this-&gt;)。

编辑 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]; }

这样做的好处是只需要一个内存分配(因此需要一个delete[])。由于单元是连续的,因此它还提高了缓存局部性。

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

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

这根本不需要内存分配(当然,new Board 除外)。

【讨论】:

  • 或者甚至从一开始就使用board,而不使用局部变量。道德:任何时候你在 C++ 中看到***,你就错了:-)
  • @KerrekSB 任何时候你在C++中看到**...你仍然做错了。 ;)
  • @muntoo:我个人同意——尽管您可能仍在使用旧的 C 接口,所以我想放轻松。实际上,我什至会说每次使用裸指针时,都应该再考虑一下 :-)
  • @Vlad:我应该转过头来问“你为什么要使用指针?” C++ 提供了广泛的类和习语选择,几乎涵盖了您可能想用指针做的所有事情,结果通常更健壮、更正确和更灵活。
  • 嗯.. 我看到我过度使用了指针,而 ** 是我真正需要的.. 但你没有提到 delete[] 错误,这也很重要。
【解决方案2】:

您需要new 的任何东西delete,方式完全相同:

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

在这种情况下不需要取消引用。

【讨论】:

    【解决方案3】:

    你应该使用 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](嗯,差不多),但不必担心释放问题。

    阅读更多关于向量的信息here。 (有人知道好的教程吗?)

    【讨论】:

    • @Vlad 为什么不呢?它当然更容易使用。您是否担心它“太复杂”?
    • 任何机会,你的意思是Board(std::vector&lt;std::vector&lt;char&gt; &gt; const&amp; board) : board(board) {}而不是你的第一个ctor?
    • @Vlad:不,不,不。一点也不。很抱歉,您上一条评论中的所有内容都是错误的。
    • 几年后读自己的cmets真的很有趣,我似乎完全无法识别自己的观点
    • @SicariusNoctis 完全正确
    猜你喜欢
    • 1970-01-01
    • 2012-08-10
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    • 2011-03-12
    • 1970-01-01
    • 2017-03-11
    • 1970-01-01
    相关资源
    最近更新 更多