1

I've stuck on a problem - I can't declare 2D arrays in C++ using integers, written by user.

This code works fine-

cin>>m>>n;
int *array;
array=new int[m*n];

But I can't make this work -

cin>>m>>n;
int *array;
array=new int[m][n];

Any ideas how i can bypass it? P.S. the error : cannot convert 'int ()[2]' to 'int' in assignment.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Nick
  • 13
  • 1
  • 5
  • You're not trying to *declare* a dynamic array (which is actually illegal in C++, all arrays must be fixed size). You're trying to *allocate* a dynamic array. – john Dec 01 '13 at 15:28

6 Answers6

2

Change

cin>>m>>n;
int *array;
array=new int[m][n];

to

cin>>m>>n;
int **array;
array=new int * [m];

for ( int i = 0; i < m; i++ ) array[i] = new int[n];
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

Firstly I suggest you should use std::vector to avoid memory allocation / deallocation issues.

In case you want an array implementation, then you can declare array as a pointer to pointer to int.

cin >> m >> n;
int** array = new int* [m];
for ( int I = 0; I < m; I++ ) {
  array[I] = new int[n];
}
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Abhishek Bansal
  • 12,589
  • 4
  • 31
  • 46
0

array is int * and you try to assign int **... change array to int**.

2D array is actually array of arrays, so you need pointer to pointer.

MeNa
  • 1,467
  • 9
  • 23
  • Well, arrays are not pointers, they only *decay* to pointers when used. Thus an array declared as `int array[m][n]` is *not* a pointer to pointer, but one consecutive slab of m arrays of length n. There is no pointer array involved. – cmaster - reinstate monica Dec 01 '13 at 13:44
  • @cmaster array is not a pointer, but the variable `array` in the question is very pointer. Please read again, i just said that he **need** pointer to pointer! – MeNa Dec 01 '13 at 13:55
  • 1
    No, you cannot have a pointer to pointer pointing to arrays of arrays. Neither the types nor the element layouts are compatible. – Lightness Races in Orbit Dec 01 '13 at 14:06
0

That's because you can only use new to allocate 1D arrays. In fact, 2D arrays are also 1D arrays, where, in most systems, all rows are simply concatenated. That is called a row-major memory layout.

You can emulate 2D arrays with a 1D array. The index conversion is:

index1 = y * m + x

This also has much better performance than creating one array per row, as recommended in the "duplicate" link or in other answers.

Domi
  • 22,151
  • 15
  • 92
  • 122
  • "you can only use new to allocate 1D arrays" is not correct, you can allocate arrays of any type, including arrays of arrays, which is nothing else than multidimensional arrays. Take a look at my answer, if you don't believe me. – cmaster - reinstate monica Dec 01 '13 at 13:41
0

You can do this:

typedef int RowType[n];
RowType *array = new RowType[m];

doStuffWith(array[y][x]);

Or, even shorter (but harder to remember):

int (*array)[n] = new (int[m][n]);

Edit:

There is a catch in C++ that array sizes must be constant for the new operator, so you can only do this if n is const. This is not a problem in C (and the reason I forgot about this), so the following works even if n and m are not const:

RowType *array = (RowType*)malloc(m * sizeof(RowType));

Of course, you can work around this restriction in C++ by doing this, which works even if both m and n are dynamic:

RowType *array = (RowType*)new int[m * n];

The typedef free version would be this:

int (*array)[n] = (int (*)[n])new int[m *n];
cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
0

Just as Domi said (but not index1=y*m+x but rather index1=x*n+y to emulate your desired notation):

int *array = new int [m*n];

int get (int x, int y) // emulates array[x][y] for array[m][n]
{
    return array[x*n+y];
}

However, I think the real 2-dimensional allocation (as Vlad from Moscow showed you) is slower in creation (and needs a bit more memory), but quicker in accessing. Cause array[x*n+y] == *(array+x*n+y), wether array[x][y] == *(*(array+x)+y), so you have one multiplication less, but one dereferenciation more, in sum I think it's quicker.

You could also create a class:

class array2d
{
private:
    int *data;
    int mm, nn;
public:
    array2d (int m, int n)
    {
        mm = m;
        nn = n;
        data = new int [m*n];       
    }
    ~array2d ()
    {
        delete[] data;
    }
    int *operator[] (int x)
    {
        return (data+x*nn);
    }
};

With it you can use

array2d arr(10,10);
arr[5][7] = 1;
mb84
  • 683
  • 1
  • 4
  • 13