I am a maths student and quite new to C++ and to help my learning I want to create a matrix class (I dont want to use a library class). I was thinking of doing something like
int iRows = 5;
int iColumns = 6;
double** pMatrix = new double*[iRows];
for (int i = 0; i < iRows; ++i) {
pMatrix[i] = new double[iColumns];
}
(I am not sure if this is the right syntax - I wanted to get advice here before trying) but I see here at Stackoverflow that using pointers that are not like shared_ptr is not recommended. Is it better to use vector<vector<double>>
so that I do not have to worry about deleting the memory? I am worried that vector is not a good choice because the length can be changed with push_back and I want the matrix to be fixed in size. I cannot use
double dMatrix[iRows][iColumns];
because the dimensions are not constant. What would be the best choice for me to use?
I would ask yourself first: what are you trying to achieve? Are you wanting to create something as a learning exercise or do you want a decent matrix implementation?
If you are wanting to do this as a learning exercise then I would suggest using only a 1d vector of doubles internally with MxN elements. Create a class that stores this internally but hides the implementation from callers -- they shouldn't know or care how it's stored. As part of the interface you would typically want to access it via operator (m,n), eg
double& MyMatrix::operator()(int m, int n) {
return m_Array[m*numColumns + n];
}
As soon as you try to do more interesting things with it such as addition and multiplication you'll realise that you'll have to overload the arithmetic operators. Not just operator+
, operator-
, but also operators *, /, *=, +=, -= /=, ++, --. When you implement multiplication you may find that your implementation may be too slow to be useful as you may find that you're making lots of redundant copies. YMMV
So if you want a fast matrix library then you'll want a library that uses BLAS internally such as Boost's Basic Linear Algebra library.
Perhaps then try it yourself first to get an idea of the problems in getting a good design then take a look at boost as you will learn a lot by studying it.
Probably
std::vector<double> matrix(rows * columns); // ditch the prefixes
// indexing: matrix[row * columns + column];
As each row will have the same number of columns anyway.
No, definitely not. Neither
vector<vector<double>> matrix;
nor
double** matrix;
are good layouts for a matrix class. Although your class may work well to get acquainted with programming, the performance of such a matrix class will be inferior. The problem is that you lose data locality. Just consider your code
for (int i = 0; i < iRows; ++i) {
pMatrix[i] = new double[iColumns];
}
For an efficient matrix-vector multiplication you should have as much matrix values as possible in the cache otherwise the memory transfers will just take too much time.
As you are acquiring one block of memory per row, nothing guarantees that these data junks are close together in memory. For a simple matrix-vector multiplication this might not be too bad because the row elements are still stored contiguously and "only" the jump from one row to the next leads to a cache miss.
However, operating on the transposed matrix is really a problem because the values along a column might be stored anywhere in the memory and there is no reasonable way to determine the stride between those elements which could be used for cache prefetching.
Thus, as suggested by the other authors, use one large block of memory for your matrix. This requires a bit more effort from your side but it will pay off for the users of your matrix class.