简体   繁体   中英

matrices vs. arrays of arrays in C++ and their dynamic allocation

There is something I still don't quite understand about the way matrices and other multidimensional arrays are represented in C and C+ and how to allocate them dynamically.

Consider the following code segment:

int main()
{
    int n;
    cin >> n;
    int a[n][n];
    ...
}

If I understand correctly, this allocates an n by n matrix of integers on the stack. The (i,j)-th element of the matrix can be accessed using a[i][j]. The compiler automatically converts this into an access into the (n*i+j)-th element of a one dimensional array actually allocated.

Suppose now that I would like to allocate the n by n matrix a on the heap, instead of the stack. I can then do the following:

int main()
{
    int n;
    cin >> n;
    int** a;
    a = new int*[n];
    for (int i=0;i<n;i++) a[i] = new int[n];
    ...
}

I can now access the (i,j)-th element again as a[i][j]. However, this is not exactly equivalent to the situation above as I actually had to allocate space for n*n int's, plus n pointers to int. Also, accessing a[i][j] now entails two accesses to memory instead of just one. On the other hand, the index computation n*i+j is avoided.

Suppose now that I am interested in n by m matrices where m is small, eg, m=2. Using the array of row pointers then wastes 33% of the space. Is there any way of avoiding that?

I can of course allocate a one-dimensional array and do the index arithmetic myself, but this does not seem to be the best solution to me.

Any information would be appreciated!

You could do

 int *mat = new int[n*n];

then use mat[n*i+j]

Rather you would allocate one linear array of ints:

int main()
{
    int n;
    cin >> n;
    int *a;
    a = new int[n*n];
}

Doing the index math yourself is a good way to go.

You could reverse the allocation order. If you are concerned about 33% or whatever memory being taken up due to "row" pointers, why not just turn the rows into the columns and vice versa? Then, instead of [i][j] you'd access an element with [j][i] . Of course, this may or may not be practical in your situation, it's hard to say without more information.

But really, I see no problems using index maths, there's nothing inherently wrong with it.

You could create a class that did the index math for you, if that's where you're not liking things.

class Matrix
{
    public:
        Matrix(int iRows, int iCols)
        : mRows(iRows), mCols(iCols), m(new int[mRows*mCols]) { }
        ~Matrix() { delete [] m; }

        int &element(int iRow, int iCol) { return m[iRow * mCols + iCol]; }

        int mRows, mCols, *m;
};

You can't do

int n;
cin >> n;
int a[n][n];

because the compiler needs to know exact size you will need on the stack during compile time. This is not possible when you are asking for it at run time :-) On the other hand you can do

#define N 10
int a[N][N];

In the other cases, you have to use dynamic allocation.

And allocation in C works just like that you allocate one piece of contiuous memory, indexes like a[i][j] are just syntactic sugar to jump into that memory, you can as well do *(a + k*i + j), where k is the size of the inner array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM