p points to an array of length 6. newint[2][3] is a "2D" array of int; with 2 rows and 3 columns. I.e. the array contains 2 elements and each element of the array is an array of 3 ints.
To store this in a variable, you need a suitable pointer. So int **p = newint[2][3]. The reason why your code worked is because multi dimensional arrays are represented as 1D arrays, but when accessed with the [][] the compiler does a simple arithmetic to determine which element to return.
// m is a matrix of 2 dimensions whose dimensions are {2, 3}.
// Internally, is a matrix of 1 dimension whose elements are stored by rows (first row 0,
// second row 1)
int m [2][3] = {{1, 2, 3},
{4, 5, 6}};
for (int i = 0; i < 2; i++){
for (int j = 0; j < 3; j++){
cout << "m[" << i << "][" << j << "]: " << m[i][j] << endl;
}
}
// pm is a pointer to a matrix of 1 dimension whose dimension is {1}
int (*pm)[3] = m;
for (int i = 0; i < 2; i++){
for (int j = 0; j < 3; j++){
cout << "pm[" << i << "][" << j << "]: " << pm[i][j] << endl;
}
}
// pm2 is a pointer to an int that pointer to the first element of the matrix m, this is, to the
// element m[0][0]
int* pm2 = reinterpret_cast<int*>(m);
for (int i = 0; i < 6; i++){
cout << "pm2[" << i << "]: " << pm2[i] << endl;
}
// new int[2][3] reserve memory dinamycally for one matrix of 2 dimensions whose
// dimensions are {2, 3}.
// Internally, is a matrix of 1 dimension whose elements are stored by rows (first row 0,
// second row 1)
pm = newint[2][3];
int contador = 1;
for (int i = 0; i < 2; i++){
for (int j = 0; j < 3; j++){
pm[i][j] = contador;
contador++;
}
}
for (int i = 0; i < 2; i++){
for (int j = 0; j < 3; j++){
cout << "pm[" << i << "][" << j << "]: " << pm[i][j] << endl;
}
}
delete [] pm;