my question is really simple (which doesn't imply that the answer will be as simple.. :D )
why do arrays in C++ include the size as part of the type and Java's do not?
I know that Java array reference variables are just pointers to arrays on the heap,but so are C++ pointers to arrays,but I need to provide a size even then. Let's analyze C++ first:
// in C++ :
// an array on the stack:
int array[*constexpr*];
// a bidimensional array on the stack:
int m_array[*constexpr1*][*constexpr2*];
// a multidimensional array on the stack:
int mm_array[*constexpr1*][*constexpr2*][*constexpr3*];
// a dynamic "array" on the heap:
int *array = new int[n];
// a dynamic bidimensional "array" on the heap:
int (*m_array)[*constexpr*] = new int[n][*constexpr*];
// a dynamic multidimensional "array" on the heap:
int (*mm_array)[*constexpr*][*constexpr*] = new int [n][*constexpr1*][*constexpr2*];
n doesn't have to be a compile time constant expression,all the elements are default initialized. Dynamically allocated "arrays" are not of type array,but the new expression yields a pointer to the first element.
So when I create a dynamic array,all dimensions apart the first one,must be constant expressions (otherwise I couldn't declare the pointer to hold their elements). Is it right??
Now to Java.I can only allocate array on the heap,since this is how Java works:
// a dynamic array on the heap:
int[] array = new int[n];
// a dynamic bidimensional array on the heap:
int[][] m_array = new int[n][];
// a dynamic multidimensional array on the heap:
int[][][] mm_array = new int [n][][];
In Java, it doesn't seem to care about array size when defining an array reference variable (it's an error in Java to explicitly provide a size),and so I just need to provide the size for the first dimension when creating the array. This allows me to create jagged array,which I'm not sure I can create in C++ (not arrays of pointers).
can someone explain me how's that? maybe what's happening behind the curtains should make it clear. Thanks.
That's because in Java, all arrays are single-dimensional. A two-dimensional array in Java is merely an array of references to one-dimensional arrays. A three-dimensional array in Java is merely a one-dimensional array of references to arrays of references to arrays of whatever base type you wanted.
Or in C++ speak, an array in Java, if it's not an array of primitive, it's an "array of pointers".
So, for example, this code:
int[][][] arr3D = new int [5][][];
System.out.println(Arrays.deepToString(arr3D));
Would yield the output:
[null, null, null, null, null]
You can decide to initialize one of its elements:
arr3D[2] = new int[3][];
And the output from the same println
would now be:
[null, null, [null, null, null], null, null]
Still no ints here... Now we can add:
arr3D[2][2] = new int[7];
And now the result will be:
[null, null, [null, null, [0, 0, 0, 0, 0, 0, 0]], null, null]
So, you can see that this is an "array of pointers".
In C++, when you allocate a multi-dimensional array the way you described, you are allocating a contiguous array which actually holds all the dimensions of the array and is initialized all the way through to the ints. To be able to know whether it's a 10x10x10 array or a 100x10 array, you have to mention the sizes.
Further explanation
In C++, the declaration
int (*mm_array)[5][3];
means "mm_array is a pointer to a 5x3 array of integers". When you assign something to it, you expect that thing to be a pointer to a contiguous block of memory, which is at least big enough to contain 15 integers, or maybe an array of several such 5x3 arrays.
Suppose you didn't mention that "5" and "3".
int (*mm_array)[][]; // This is not a legal declaration in C++
Now, suppose you are handed a pointer to a newly allocated array, and we have statements like:
mm_array[1][1][1] = 2;
Or
mm_array++;
In order to know where to put the number, it needs to know where index 1 of the array is. Element 0 is easy - it's right at the pointer. But where is element 1? It's supposed to be 15 ints after that. But at compile time, you won't know that, because you didn't give the sizes. The same goes for the ++
. If it doesn't know that each element of the array is 15 ints, how will it skip that many bytes?
Furthermore, when is it a 3x5 or a 5x3 array? If it needs to go to element mm_array[0][2][1]
, does it need to skip two rows of five elements, or two rows of three elements?
This is why it needs to know, at compile time, the size of its base array. Since the pointer has no information about sizes in it, and merely points to a contiguous block of integer, that information will need to be known in advance.
In Java, the situation is different. The array itself and its sub-arrays, are all Java objects. Each array is one-dimensional. When you have an expression like
arr3D[0][1][2]
arr3D
is known to be a reference to an array. That array has length and type information, and one dimension of references. It can check whether 0
is a valid index, and dereference the 0
th element, which is itself a reference to an array.
Which means that now it has type and length information again, and then a single dimension of references. It can check whether 1
is a valid index in that array. If it is, it can go to that element, and dereference it, and get the innermost array.
Since the arrays are not a contiguous block, but rather references to objects, you don't need to know sizes at compile time. Everything is allocated dynamically, and only the third level (in this case) has actual contiguous integers in it - only a single dimension, which does not require advance calculation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With