<< i'm using an array of arrays, but you can also just have one long array, so that a 2x2 array would really be a one dimensional array of 4. >>
Well.. you have 2 different problems/difficulties with both methods.
With the first, assuming a dynamically allocated array of arrays, which would be a pointer of pointers, in order to delete, you would need to loop through the "outer" array, and delete [] the individual pointers, and then delete[] the "outer" array. I've never tried it personally but I suppose it should work (as I have used it when reading command line arguments I guess.. like char **argv vs char *argv[]).
With the second, you can allocate the a one dimensional array/pointer, but you cannot address it as array[x][y], because the compiler does not know how "wide" the array is.
array[x][y] is the same as *(array+(x*arrayWidth+y)*sizeof(yourType)).
Say you allocated 16 "blocks" for your array. You use it with say array[1][3]. The address that gets calculated will be different (err.. could be because I'm too lazy to work out the math) if the array is 1x16 (buffer overflow in this case), 2x8, or 4x4 (etc.. you get the picture).