If N
and M
are constants, it is better to just statically declare the memory you need as a two dimensional array. Or, you could use std::array
.
std::array<std::array<double, M>, N> data;
If only M
is a constant, you could use a std::vector
of std::array
instead.
std::vector<std::array<double, M>> data(N);
If M
is not constant, you need to perform some dynamic allocation. But, std::vector
can be used to manage that memory for you, so you can create a simple wrapper around it. The wrapper below returns a row
intermediate object to allow the second []
operator to actually compute the offset into the vector
.
template <typename T>
class matrix {
const size_t N;
const size_t M;
std::vector<T> v_;
struct row {
matrix &m_;
const size_t r_;
row (matrix &m, size_t r) : m_(m), r_(r) {}
T & operator [] (size_t c) { return m_.v_[r_ * m_.M + c]; }
T operator [] (size_t c) const { return m_.v_[r_ * m_.M + c]; }
};
public:
matrix (size_t n, size_t m) : N(n), M(m), v_(N*M) {}
row operator [] (size_t r) { return row(*this, r); }
const row & operator [] (size_t r) const { return row(*this, r); }
};
matrix<double> data(10,20);
data[1][2] = .5;
std::cout << data[1][2] << '\n';
In addressing your particular concern about performance: Your rationale for wanting a single memory access is correct. You should want to avoid doing new
and delete
yourself, however (which is something this wrapper provides), and if the data is more naturally interpreted as multi-dimensional, then showing that in the code will make the code easier to read as well.
Multiple allocations as shown in your second technique is inferior because it will take more time, but its advantage is that it may succeed more often if your system is fragmented (the free memory consists of smaller holes, and you do not have a free chunk of memory large enough to satisfy the single allocation request). But multiple allocations has another downside in that some more memory is needed to allocate space for the pointers to each row.
My suggestion provides the single allocation technique without needed to explicitly call new
and delete
, as the memory is managed by vector
. At the same time, it allows the data to be addressed with the 2-dimensional syntax [x][y]
. So it provides all the benefits of a single allocation with all the benefits of the multi-allocation, provided you have enough memory to fulfill the allocation request.