Slices

Los slices son objetos de tipo T[] para cualquier tipo T que proporcionan una vista de un subconjunto de un array de valores de tipo T, o simplemente una vista del array completo.

Los *slices* y los arrays dinámicos son la misma cosa.

Un slice está formado por dos miembros: un puntero al primer elemento y otro elemento con la longitud de dicho slice:

T* ptr;
size_t length; // entero sin signo del número de bits de la arquitectura

Obtener un slice mediante la sentencia new

Cuando se crea un nuevo array dinámico, lo que se devuelve es un nuevo slice a la memoria reservada por dicho array:

auto arr = new int[5];
assert(arr.length == 5); // memoria referenciada en arr.ptr

La memoria reservada en este caso está totalmente gestionada por el recolector de basura (garbage collector en inglés). El slice devuelto actúa como una “vista” de los elementos subyacentes.

Obtener un slice de memoria previamente reservada

Al usar el operador para crear slices también se puede obtener otro slice que apunte a memoria que ya ha sido reservada. Este operador también se puede aplicar a otro slice, a arrays estáticos, a clases y a estructuras que implementen el operador opSlice, y a varias entidades más.

En la expresión de ejemplo origin[start .. end], el operador de slice se usa para obtener un slice de todos los elementos de origin desde start hasta el elemento anterior a end:

auto newArr = arr[1 .. 4]; // el índice 4 NO se incluye
assert(newArr.length == 3);
newArr[0] = 10; // cambia newArr[0], es decir, arr[1]

Estos slices generan una nueva vista de memoria ya reservada, es decir, no reservan ninguna copia de la misma. Si ya no hay ningún slice que referencie un bloque de memoria (o una parte de la misma), esta memoria será liberada por el recolector de basura.

Al usar slices es posible escribir código muy eficiente para ciertas cosas (como parsers, por ejemplo) ya que sólo operan en un bloque de memoria y las partes que realmente se necesitan para trabajar. De este modo no hay ninguna necesidad de reservar nuevos bloques de memoria.

Como se ha visto en la sección anterior, la expresión [$] es una forma corta de escribir arr.length. Es por esto que arr[$] referencia el elemento más allá del último del slice, por lo que se generará un error de tipo RangeError (si la comprobación de límites no está desactivada).

En profundidad

rdmd playground.d