1

对 C++ 要求在二维数组中传递维度的烦恼让我开始研究模板化的 Matrix 类。我已经用 C# 编码了一段时间,所以我确定我在这里有点生疏了。

问题是,当我点击试图删除二维数组的析构函数时,我得到了一个堆异常。

任何帮助感激地接受!

template <typename T>
class Matrix {
public:
    Matrix(int m, int n) : nRows(m), nCols(n) { 
        pMatrix = new T * [nRows]; 
        for (int i = 0; i < nCols; i++) {
            pMatrix[i] = new T[nCols];
        }
    }
    ~Matrix() { 
        if (pMatrix != NULL) { 
            for (int i = 0; i < nRows; i++) { delete[] pMatrix[i]; }
            delete[] pMatrix;
        }
    }
    T ** GetMatrix() const { return pMatrix; }
    T * Row(int i) const { return pMatrix[i]; }
    inline T Cell(int row, int col) const { return pMatrix[row][col]; }
    inline int GetNRows() const { return nRows; }
    inline int GetNCols() const { return nCols; }
private:
    int nRows, nCols;
    T ** pMatrix;
};
4

2 回答 2

3

这是错误:

for (int i = 0; i < nCols; i++) {
        pMatrix[i] = new T[nCols];
}

循环应该是直到nRows,而不是nCols

除此之外,让我告诉你我厌倦了分配二维数组时所做的一些事情。我必须做一个 3-d 数组。我使用了一个map从坐标映射的 , - 一个将 x, y, z 保存到我想要的类型的结构。

我工作得很快,不需要分配或解除分配。分配给坐标只需通过

mymap[Coord(x, y, z)] = whatever...

当然,我需要定义Coordstruct 并重载< operator,但我发现这种方式比尝试分配和取消分配 3-d 数组更方便。

当然,您需要检查此方案是否对您来说足够快。我用它使用 OpenGL 在一个大立方体内绘制单元格,完全没有抱怨。

于 2012-12-02T08:01:55.180 回答
1

关于这个错误,@CodeChords_man 解释得很对。我有关于实施的说明。我建议查看这篇精彩的常见问题解答帖子

除非您 100% 确定,否则不应使用动态内存分配

  1. 真的需要它
  2. 你知道如何实现它

我不知道第一个,以及性能对您来说如何至关重要。但至于第二个,你至少违反了三的规则。你的课使用起来很不安全。如果复制它,则内存缓冲区将被双重删除。

您不应该害怕使用 STL 容器,它们快速且经过优化。至少std::vector,在很多场景下它和原始指针一样快。您可以使用std::vector如下方式重写您的课程:

template <typename T>
class Matrix {
public:
  typedef std::vector<T> MatrixRow;
  typedef std::vector<MatrixRow> MatrixBody;

  Matrix(int m, int n) : nRows(m), nCols(n), _body(m, MatrixRow(n)) {}

  const MatrixBody& GetMatrix() const { return _body; }
  const MatrixRow& GetRow(int i) const { return _body[i]; }

  inline T Cell(int row, int col) const { return _body[row][col]; }
  inline int GetNRows() const { return nRows; }
  inline int GetNCols() const { return nCols; }
private:
  int nRows, nCols;
  MatrixBody _body;
};

由于此类不使用动态内存分配,因此复制和分配是安全的。在这种情况下,您也不需要显式存储nRows和;nCols你可以使用_body.size()and_body[0].size()代替。

关于向量的底层向量,它使用相同的[i][j]结构被取消引用。它很容易用begin()和迭代end()。如果您绝对需要在某些例程中使用原始指针,您可以随时使用&row[0].

唯一可能的困难是您无法轻松转换MatrixBodyT**. 但是三思而后行,也许你根本不需要使用T**

于 2012-12-02T10:11:08.427 回答