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.

1
  • 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
    Commented Dec 1, 2013 at 15:28

6 Answers 6

1

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];
7
  • Do not forget to delete all allocated pointers. Commented Dec 1, 2013 at 13:43
  • 6
    Do not forget to explain your answer instead of harmfully dumping code on those who do not understand it. Commented Dec 1, 2013 at 14:06
  • This isn't a multidimensional array; it's an array of pointers to 1D arrays. See How do I declare a 2d array in C++ using new? - apparently C++11 does allow new int [nrows][CONSTANT];. Compilers that support variable-length arrays as an extension can at least cast raw memory to runtime-variable sized 2D arrays as well. Commented Nov 13, 2023 at 20:00
  • @PeterCordes This array=new int * [m]; is not a variable length array, Your comment does not make sense. It seems you are overqualified.:) Commented Nov 13, 2023 at 22:30
  • My point was that C++ can't dynamically allocate proper 2D arrays the same way C99 allows (Freaky way of allocating two-dimensional array?), except maybe with C++ extensions. Giving up and doing inefficient allocation of each row separately is not a good alternative. If you insist on an array of pointers, PaulMcKenzie's answer on how to create a contiguous 2d array in c++? shows how to do that with two news, one big array for all the int data, and one for pointers into it. Commented Nov 13, 2023 at 22:41
1

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];
5
  • No you cannot ;) If anything then n must be constant, i belive this is not a case here. Commented Dec 1, 2013 at 13:42
  • To be able to do it like this n must be constatant, and it isn't in this case. Commented Dec 1, 2013 at 13:49
  • @Bartek You are right, there is a catch in C++. Not nice. C doesn't have such interesting restrictions... Commented Dec 1, 2013 at 14:06
  • @Bartek Found a way to work around this C++ restriction without resorting to malloc() :-) Commented Dec 1, 2013 at 14:18
  • C doesn't have this problem because C doesn't have new keyword ;) so since you are doing malloc anyway, then it's moving responsibility to lower level functions. Beside sizeof type is calculated in the runtime so typedef which is not used in new keyword can be passed to sizeof() function without any problems. Commented Dec 1, 2013 at 14:28
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.

3
  • 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. Commented Dec 1, 2013 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
    Commented Dec 1, 2013 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. Commented Dec 1, 2013 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.

1
  • "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. Commented Dec 1, 2013 at 13:41
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;
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];
}
1
  • Thanks, didn't know about vectors.
    – Nick
    Commented Dec 1, 2013 at 13:43

Not the answer you're looking for? Browse other questions tagged or ask your own question.