views:

205

answers:

4

Hi,

I am trying to dynamically assign a 2d array to a pointer in a constructor initialize.

FooBar::FooBar()
    : _array( new int[10][10] )
{ }
int **_array;

However this does not work. I understand that multidimensional arrays are allocated a bit differently. Is anyone able to elaborate on this with an explanation?

Thanks in advance.

+3  A: 
int **array  = new int *[10];

for(int i= 0; i< 10;i++)
{
    array[i] = new int[10];
}
Ashish
A: 

If you're using new, you need to allocate each piece of the second dimension individually.

int **Array;
Array = new int*[10];
for (int i = 0; i < 10; i++) {
    Array[i] = new int[10];
}
Seisatsu
Oops, someone got here first.
Seisatsu
+4  A: 

A 2-dimensional array in C is an array of pointers to other arrays.

Assuming we have the 3x3 array a (typed int**):

a[0] (a[0] is of type int*) = [0][1][2]
a[1] (a[1] is of type int*) = [0][1][2]
a[2] (a[2] is of type int*) = [0][1][2]

That means that two allocation passes are needed, one for the array of pointers, (int**) and the rest is for each of that array's elements.

First pass, allocating an array of pointers:

int** a = new int*[10];

Second pass, for each of a's elements, allocating a new array:

for(int i=0; i<10; ++i)
    a[i] = new int[10];

This will give you a 'two' dimensional array in C++.

As you can see, this can be pretty cumbersome in higher dimensions, so another trick is to allocate 10*10 elements and use the array as 2D (aka "projection"):

const int ARRAY_WIDTH = 10;
const int ARRAY_HEIGHT = 10;
int* a = new int[ARRAY_WIDTH * ARRAY_HEIGHT];

    // To access a[5][2] you would use: 
a[5 + (2 * ARRAY_WIDTH)] = 0;
LiraNuna
-1 - a 2D array in C/C++ is not the same as an array of pointers to arrays, nor does it have a pointer type.
Pavel Minaev
-1, There is no such language as C/C++.
LiraNuna
+5  A: 

Some answers here say a 2-dimensional array is an array of pointers to other arrays. That's not true (where to store pointers, if all you allocate is the data of the array!?). Instead, a 2-dimensional array is an array of other arrays. Thus, you will have to change the type of your member:

FooBar::FooBar()
    : _array( new int[10][10] )
{ }
int (*_array)[10];

That is because new[] returns a pointer to the first element of an array created. This element is an array of 10 integers, and thus the member type change. If the syntax scares you off, simplify it with a temlate (this template is equivalent to boost::identity).

template<typename T> struct identity { typedef T type; };

FooBar::FooBar()
    : _array( new int[10][10] )
{ }
identity<int[10]>::type *_array;

This effectively works like a in-place typedef. Of course, like with any use of new[], it needs a proper delete[] placed in the destructor and invoked when your object is destroyed.

Since new[] allocates an array of elements that have types known at compile time, you can only have the first (most outer) dimension set to a runtime value - all others must have values known at compile time. If that is not what you want, you will have to allocate an array of pointers, like some other answers say.

But notice, to avoid further confusion, that those are not multi-dimensional arrays. They are single-dimensional arrays of pointers, which happen to point at other single-dimensional arrays.

Johannes Schaub - litb