1

I am studying c++ and found this in the book

array_ptr = new int[3][5][4];

This is used to allocate memory to a multi dimensional array using new. It also states while first dimension can be a variable whose value is supplied at runtime, others must be constant. I tried to run this code

int *p = new int[3][5][6];

But it is showing an error. Can someone elaborate.

daljinder singh
  • 177
  • 1
  • 9
  • 2
    Throw away that book and replace it with [something saner](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – nwp May 16 '17 at 14:15
  • 3
    By all means, don't copy the error message into your question. People might actually be able to tell you the error message means there is a type mismatch between `int*` and `int (*)[5][6]`. – FRob May 16 '17 at 14:23
  • 1
    @FRob why are you so frustrated dude, calm down – daljinder singh May 16 '17 at 14:27
  • This is a C answer, but as far as how raw arrays work, it applies to C++ as well: [Correctly allocating multi-dimensional arrays](http://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays). Please use this to smack around everyone who is babbling about pointer-to-pointer-to-pointer-to... – Lundin May 16 '17 at 15:29
  • @nwp What's wrong with OPs book? The only problem I see is that it didn't say what type `array_ptr` must have. – HolyBlackCat May 16 '17 at 16:01
  • 1
    @HolyBlackCat The book apparently teaches pointer fiddling and doing manual memory management which is difficult and unnecessary. It shows that the author doesn't know about relevant coding practices or doesn't care. I may have been a bit hasty and the book actually shows why to not do such a thing right after or just as a side note, but chances are it is written by an author who thinks C++ is basically C which is basically fortran. Since this is unfortunately common and very damaging to ones learning and abilities later on I felt the need to advice an alternative. – nwp May 16 '17 at 16:19

3 Answers3

2

Here is what you want:

int (*p)[5][6] = new int[3][5][6];

Since C++11 you can ask the compiler to decuce the type of p for you:

auto p = new int[3][5][6];

You don't need anything special to delete such array:

delete [] p;

Logic behind the choice of the type is simple:

In this line: int *p = new int[10] you're creating an array of 10 ints and you use pointer to int to store the address.

In general case, if you're allocating an array of N Ts (where N is the size and T is the type), you use pointer to T to store the address.

Same rule can be applied to multidimensional arrays, because they are in fact nested 1D arrays.

When you try to allocate multidimensional array: p = new int[4][5][6], you're creating an array of 4 arrays of 5 arrays of 6 ints. Thus you need a pointer to array of 5 arrays of 6 ints, which is int (*p)[5][6].

In other words, int [3][4][5] can be viewed as 1D array of size 3. It consists of other arrays of type int [4][5]. Each of these arrays has size 4 and consists of other arrays of type int [5], which in turn contain 5 ints.


P.S. Authors of other answers seem to favor using int *** and allocating memory for each nested array separately. Doing so may seem smart, but in fact it's much slower and dangerous (if you mess up your memory management). The only advantage of that trick is that it provides the convenient interface we all used to (p[z][y][x]).

But there is a much better solution: int *p = new int[x_sz * y_sz * z_sz];. You would need to convert 3D indices to 1D index (p[x + x_sz * (y + z * y_sz)] instead of p[z][y][x]) for it to work, but in my opinion it's still more convenient (and definitely faster).

Of course, in real code, you should use std::vector to store such array and write your own wrapper class, which would compute the index automatically.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
-1

A 3d array is not the same as a pointer to int, and you can't make them the same.

If you need dynamic allocation, you can use special class std::vector (best choose), std::array, or write next code:

int ***p = new int**[3];
for (int i = 0; i < 3; ++i) {
  p[i] = new int*[5];
  for (int j = 0; j < 5; ++j) {
    p[i][j] = new int[6];
  }
}
knst
  • 523
  • 2
  • 16
-1

In order to create dynamic 3d array you have to use pointer to pointer to pointer)

const int xSize = 3;
const int ySize = 5;
const int zSize = 4;

int*** p = nullptr;

// creating array of pointers to pointers
p = new int** [xSize]

// for each pointer to pointers, create array of pointers
for( int i = 0; i < xSize; ++i )
  p[ i ] = new int* [ySize];

// now we have 2d array of pointers, for each of them allocate array
for( int i = 0; i < xSize; ++i )
  for( int j = 0; j < ySize; ++j )
    p[ i ][ j ] = new int [zSize];

But is much more better to use vectors

vector<vector<vector<int> > > v3d;

v3d.resize( 3 );

for( int i = 0; i < xSize; ++i )
  v3d[ i ].resize( ySize );

for( int i = 0; i < xSize; ++i )
  for( int j = 0; j < ySize; ++j )
    v3d[ i ][ j ].resize( zSize );
oybek
  • 630
  • 4
  • 14