First of all: I STRONGLY suggest you to use, when possible, standard C++ containers; in 2D case (caution: not tested)
std::vector<std::vector<GridUnit> > gu2d (width, std::vector<GridUnit>(height));
I strongly suggest this especially if isn't absolutely clear the example that you mention.
Consider if you access at position i
, j
gu2d[i][j] = GridUnit();
where, by mistake, j
value is height
; without realizing it, you modify gu2d[i+1][0]
. If gu2d
is a vector of vectors, with gu2d.at(i).at(j)
you obtain bound checking and a nice exception.
- why is the grid defined as pointers to arrays of length = width and the iteration takes place over an index going up to width shifting the address by height?
You can see a 2D matrix as an array of width
rows of cells where each row is of height
cells.
So the first pointer (newGrid
) has lenght width
because it references width
rows.
Every row has length height
, so the width
values referenced by newGrid
are separated (shifted) by a space of height
(in pointer metric).
I think you can be clearer if you read the first answer to this question
How do I declare a 2d array in C++ using new?
- Should I then declare an array of length=width with pointers to arrays of length=height*depth which would result in the following code
I'm not an English native speaker but it seems to me that you have chosen an unhappy order of names. I suppose you should use depth
before width
.
But, using your actual names (width
is the dimension of the first index, height
of the second, depth
of the third)...
Exactly.
Your code should change
newGrid = new int**[height*depth];
width
newGrid = new int**[width];
In the 3D case, you can see newGrid
as (with your choose one names) an array of width
2D matrix where the 2D matrix are array of height
rows of depth
cells. So every 2D matrix is of size heigth * depth
.
Caution: remember to delete with
delete newGrid[0][0];
delete newGrid;
p.s.: sorry for my bad English
--- EDIT ---
Sorry: I haven't seen a point that is important about your hypotesis of new3dGrid
: you should allocate three pointers, not two: newGrid
, as int***
, for size width
; newGrid[0]
, as int**
for size width * height
; newGrid[0][0]
, as int*
, for size width * height * depth
. The three types of pointers need different allocated area.
I propose the different template version (caution: not tested) [corrected by Ben Voigt; thanks!]
template <typename T>
T*** new3dGrid (unsigned height, unsigned width, unsigned depth)
{
T*** newGrid;
newGrid = new T**[width];
newGrid[0] = new T*[width * height];
newGrid[0][0] = new T[width * height * depth];
for ( unsigned i = 0U ; i < width ; ++i )
{
if ( i > 0U )
{
newGrid[i] = newGrid[i-1U] + height;
newGrid[i][0] = newGrid[i-1U][0] + height * depth;
}
for ( unsigned j = 1U ; i < height ; ++j )
newGrid[i][j] = newGrid[i][j-1U] + depth;
}
return newGrid;
}
and you should delete three pointers
delete newGrid[0][0];
delete newGrid[0];
delete newGrid;
Sorry.