While many people like your approach, if you want it to be fast (like, for example, with a matrix, you need one block of memory and index it yourself.
There are several reasons for this. First, you need to allocate one memory block for the top-level vector and one vector for each row (or column, since you are from FORTRAN ....)
So, instead of a single operation, you have n + 1.
This applies every time you process this object, copy, destroy what you have. You also save vector overhead (size, capacity) for each row. Of course, if each row has a different size, this is a function.
So, consider the following, hard-coded twice for clarity: See how simple the constructor is, and how simple the operation is, such as + =, because it can just go through the entire block sequentially, ignoring indexing.
It also indexes a single item more slowly through two arrays. The computer must access the top-level vector from the object, find the pointer, jump over there and find the second pointer.
Custom indexing is provided in the () operator
class Matrix { private: int m_rows, m_cols; double* m_data; public: Matrix(int rows, int cols) : m_rows(rows), m_cols(cols), m_data(new double[rows*cols] {} ~Matrix() { delete [] m_data; } Matrix(const Matrix& orig) m_rows(orig.m_rows), m_cols(orig.m_cols), m_data(new double[m_rows * m_cols] {}