1

我是一名数学学生,对 C++ 很陌生,为了帮助我的学习,我想创建一个矩阵类(我不想使用库类)。我正在考虑做类似的事情

int iRows = 5;
int iColumns = 6;
double** pMatrix = new double*[iRows];
for (int i = 0; i < iRows; ++i) {
    pMatrix[i] = new double[iColumns];
}

(我不确定这是否是正确的语法 - 在尝试之前我想在这里获得建议)但我在 Stackoverflow 看到不推荐使用不像 shared_ptr 的指针。是不是更好用vector<vector<double>>,这样我就不用担心删除内存了?我担心向量不是一个好的选择,因为长度可以用 push_back 改变,我希望矩阵的大小是固定的。我不能使用

double dMatrix[iRows][iColumns];

因为尺寸不是恒定的。什么是我使用的最佳选择?

4

3 回答 3

5

大概

std::vector<double> matrix(rows * columns); // ditch the prefixes
// indexing: matrix[row * columns + column];

因为无论如何每一行都将具有相同数量的列。

于 2012-08-13T18:00:49.323 回答
2

我会先问自己:你想达到什么目标?您是想创建一些东西作为学习练习,还是想要一个体面的矩阵实现?

如果您想将此作为学习练习,那么我建议仅在内部使用带有 MxN 元素的一维双精度向量。创建一个在内部存储它但对调用者隐藏实现的类——他们不应该知道或关心它是如何存储的。作为界面的一部分,您通常希望通过运算符 (m,n) 访问它,例如

double& MyMatrix::operator()(int m, int n) {
  return m_Array[m*numColumns + n];
} 

一旦你尝试用它做更有趣的事情,比如加法和乘法,你就会意识到你必须重载算术运算符。不仅operator+, operator-,还有运算符 *、/、*=、+=、-= /=、++、--。当您实现乘法时,您可能会发现您的实现可能太慢而无法使用,因为您可能会发现您正在制作大量冗余副本。YMMV

因此,如果您想要一个快速的矩阵库,那么您将需要一个在内部使用 BLAS 的库,例如 Boost 的基本线性代数库

也许然后自己先尝试一下,以了解获得良好设计的问题,然后看看 boost,因为您将通过研究它学到很多东西。

于 2012-08-13T18:21:27.443 回答
1

不,绝对不是。两者都不

vector<vector<double>> matrix;

也不

double** matrix;

是矩阵类的好布局。尽管您的课程可能会很好地熟悉编程,但此类矩阵课程的性能会较差。问题是您丢失了数据局部性。只需考虑您的代码

for (int i = 0; i < iRows; ++i) {
    pMatrix[i] = new double[iColumns];
}

对于有效的矩阵向量乘法,您应该在缓存中拥有尽可能多的矩阵值,否则内存传输将花费太多时间。当您每行获取一个内存块时,无法保证这些数据垃圾在内存中紧密相连。对于简单的矩阵向量乘法,这可能并不算太糟糕,因为行元素仍然是连续存储的,并且“只有”从一行到下一行的跳转会导致缓存未命中。

但是,对转置矩阵进行操作确实是一个问题,因为沿列的值可能存储在内存中的任何位置,并且没有合理的方法来确定可用于缓存预取的那些元素之间的步幅。

因此,正如其他作者所建议的那样,为您的矩阵使用一大块内存。这需要您付出更多的努力,但它会为您的矩阵类的用户带来回报。

于 2012-08-17T17:18:28.950 回答