Les tranches sont des objets de type T[]
pour n'importe quel type T
.
Les tranches sont une abstraction qui représentent une partie d'un tableau de valeur de type T
, ou le tableau en entier.
Les tranches et les tableaux dynamiques représentent la même chose.
Une tranche contient deux membres : un pointeur vers l'élément de départ et la longueur de la tranche :
T* ptr;
size_t length;
new
Si un nouveau tableau dynamique est créé, une tranche qui pointe vers son espace mémoire est retournée:
auto tab = new int[5];
assert(tab.length == 5); // mémoire référencée par tab.ptr
Dans ce cas, la mémoire allouée est gérée par le ramasse-miettes. La tranche retournée agit comme une "vue" des éléments sous-jacents.
Utiliser l'opérateur de tranchage permet de récupérer une tranche pointant vers une zone mémoire qui a déjà été allouée. L'opérateur de tranchage peut être appliqué à une autre tranche, à un tableau statique, à des structs
ou des classes qui implémentent la méthode opSlice
et à quelques autres entités.
Dans une expression origine[start..end]
, l'opérateur de tranchage est utilisé pour obtenir une tranche de tous les élements d'origine
de start
à l'élément avant end
:
auto newTab = tab[1 .. 4]; // l'élément d'indexe 4 n'est PAS inclus
assert(newTab.length == 3);
newTab[0] = 10; // change newTab[0], soit tab[1]
Ces tranches créent une nouvelle vue sur une zone de mémoire déjà existante. Elles ne créent pas une nouvelle copie. S'il n'y a plus de tranche qui référence cette zone de mémoire, ou sur une partie de cette zone, elle sera libérée par le ramasse-miettes.
En utilisant les tranches, il est possible d'écrire du code très efficace pour des choses (les parsers par exemple) qui n'opèrent que sur une zone mémoire, et tranche uniquement la partie sur laquelle elle doit travailler. De cette façon, on évite d'allouer des nouveaux blocs en mémoire.
Comme nous l'avons vu dans la partie précédente, l'expression [$]
est une forme raccourcie de tab.length
. Donc tab[$]
représente l'élément juste après le dernier de la tranche, et générerait une RangeError
(si les vérifications d'accès par indexe n'ont pas été désactivées).