All of your allocation and deallocation code can be replaced by
std::vector<std::vector<float>> matrix(m, std::vector(n));
Seriously. It even deallocates itself when it goes out of scope, so you have almost no memory management issues.
#include <iostream>
#include <vector>
int main()
{
size_t m;
size_t n;
std::cin >> m >> n;
// floats initialized to 0.0
std::vector<std::vector<float>> fltmatrix(m, std::vector<float>(n));
// doubles initialized to 0.0
std::vector<std::vector<double>> dblmatrix(m, std::vector<double>(n));
// bools initialized to true
std::vector<std::vector<bool>> boolmatrix(m, std::vector<bool>(n), true);
// ints initialized to 42
std::vector<std::vector<int>> intmatrix(m, std::vector<int>(n, 42));
} <-- all vectors are released here.
Practically no effort required.
However, because each vector is it's own independent entity and you have m+1 vectors, you have m+1 different places in memory that your program needs to look to return a value. This can have a really bad impact on your programs performance as small matrices, say a 3x3, can't take full advantage of the CPU's caching and this can be very, very noticeable when crunching large numbers of matrices. If you don't care, stop reading and go with the simple vector of vector approach.
If you do care, wrap a 1D vector in a class:
#include <iostream>
#include <vector>
template<class TYPE>
class Matrix
{
private:
size_t rows, columns;
std::vector<TYPE> matrix;
public:
Matrix(size_t numrows, size_t numcols) :
rows(numrows), columns(numcols), matrix(rows * columns)
{
}
Matrix(size_t numrows, size_t numcols, TYPE init) :
rows(numrows), columns(numcols), matrix(rows * columns, init)
{
}
TYPE & operator()(size_t row, size_t column)
{
// check bounds here
return matrix[row * columns + column];
}
TYPE operator()(size_t row, size_t column) const
{
// check bounds here
return matrix[row * columns + column];
}
size_t getRows() const
{
return rows;
}
size_t getColumns() const
{
return columns;
}
friend std::ostream & operator<<(std::ostream & out, const Matrix & in)
{
for (int i = 0; i < in.getRows(); i++)
{
for (int j = 0; j < in.getColumns(); j++)
{
out << in(i, j) << ' ';
}
out << std::endl;
}
return out;
}
};
int main()
{
size_t m;
size_t n;
std::cin >> m >> n;
// floats initialized to 0.0
Matrix<float> fltmatrix(m, n);
std::cout << fltmatrix << std::endl;
// doubles initialized to 0.0
Matrix<double> dblmatrix(m, n);
std::cout << dblmatrix << std::endl;
// bools initialized to true
Matrix<bool> boolmatrix(m, n, true);
std::cout << boolmatrix << std::endl;
// ints initialized to 42
Matrix<int> intmatrix(m, n, 42);
std::cout << intmatrix << std::endl;
}
More effort, but should be faster. Profile your program to see if Matrix
is right for you.
operator<<
is included as an output convenience and as an example of how to access Matrix
's cells.
And if you just have to use an array... Things get a lot uglier. For one thing, you will have to be Rule of Three (and possibly Rule of Five) compliant and pick up a bunch of extra functions that, frankly, you're probably not going to get right the first few times.
I'm not even sure I can get it right if I just bang one out, and I have a perfectly good alternative, so I'm not going to. What you can gain is a matrix that does not spend time initializing the matrix before use. If that is an issue (profile, profile, profile!) I'd call that a new question. The current question uses calloc
so it doesn't look like OP is concerned.