2011-12-14 10 views
8

Es curioso si esta es la mejor práctica para inicializar una matriz dinámica y multidimensional en D. Hay una sección sobre arreglos en su referencia de lenguaje, pero no estoy seguro de si se trata de lo que estoy tratando de lograr.Lenguaje D: ¿inicialización de mejores prácticas dinámicas de matriz multidimensional?

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 

(o una alternativa equivalente como un típico para (y = 0; y < altura; y ++) circular).

Mi preocupación con esto es que reasigna cada fila de la matriz por separado en lugar de todo el fragmento a la vez, por lo que no sé si esto dará lugar a demasiada memoria. Además, creo que no está garantizado que sea contiguo (dado que , las teselas son solo una matriz de punteros en este caso). ¿Hay alguna forma "mejor" de hacer esto (que no implique el uso de una matriz unidimensional y el cálculo del índice por mi cuenta)? Por lo que puedo decir de los documentos, una matriz contigua multidimensional solo se puede declarar con dimensiones inmutables en tiempo de compilación, solo me pregunto si me falta algo ...

Respuesta

17

puede nueva la matriz, por lo menos en D2:

Tile[][] tiles = new Tile[][](height, width); 

Creo que esta es la mejor práctica.

+2

Bien técnicamente, la práctica _best_ usaría 'auto' en el lado izquierdo en lugar de repetir el tipo. Pero sí, esta es la mejor manera de asignar una matriz multidimensional siempre que se suponga que cada una de ellas tenga la misma longitud. –

+0

Esto parece hacer el truco, ¡gracias! – ccjuju

+0

Ver también [http://www.d-programming-language.org/expression.html#NewExpression](http://www.d-programming-language.org/expression.html#NewExpression). – XP1

3

puede fudge it malloc todo lo que necesita adelantado

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 
} 

EDITAR o utilizar una matriz temporal para mantener el dobladillo en menos de un código más limpio/bugprone (es decir, ocultar el 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 
} 
+0

+1 - ¡No pensé en esto! :) ¡Gracias por la pista! – DejanLekic

+1

Nota pequeña para la primera muestra: puede usar enforceEx, p. Ej. 'enforceEx! OutOfMemoryError (GC.malloc (Tile.sizeof * width * height));', tampoco es 'OutOfMemoryException', sino' OutOfMemoryError', y estos requieren importaciones a 'std.exception',' core.memory' y 'core.exception'. –