Reputation: 507
Just curious if this is the best practice for initializing a dynamic, multidimensional array in D. There is a section on arrays in their language reference, but I'm not quite sure if it goes over what I'm trying to accomplish.
class Map {
Tile[][] tiles;
this(uint width, uint height) {
tiles.length = height;
foreach (ref tilerow; tiles)
tilerow.length = width;
}
}
Map map1 = new Map(5000, 3000); // values determined at runtime
(or an equivalent alternative like a typical for (y=0;y<height;y++) loop).
My concern with this is that it reallocates each row of the array separately rather than the whole chunk all at once, so I don't know if this will lead to too much memory shuffling. Also, I believe it's not guaranteed to be contiguous (since tiles is just an array of pointers in this case). Is there any "better" way to do this (that doesn't involve using a single-dimensional array and computing the index myself)? As far as I can tell from the docs a contiguous multidimensional array can only be declared with immutable dimensions at compile time, just wondering if I'm missing something...
Upvotes: 11
Views: 2234
Reputation: 2077
You can new the array, at least in D2:
Tile[][] tiles = new Tile[][](height, width);
I believe this is the best practice.
Upvotes: 18
Reputation: 48216
you can fudge it by malloc
ing every thing you need upfront
this(uint width, uint height) {
void* p = enforce(GC.malloc(Tile.sizeof*width*height),new OutOfMemoryException);
//allocate all rows at once, throw on returned null
tiles.length = height;
foreach (i,ref tilerow; tiles)
tilerow = cast(Tile[])p[Tile.sizeof*width*i..Tile.sizeof*width*(i+1)];
//slice it into the multidimensional array
}
EDIT or use a temporary array to keep hem in for cleaner/less bugprone code (i.e. hide the malloc)
this(uint width, uint height) {
Tile[] p = new Tile[height*width]
tiles.length = height;
foreach (i,ref tilerow; tiles)
tilerow = p[width*i..width*(i+1)];
//slice it into the multidimensional array
}
Upvotes: 3