En Swift, les types de valeur (value types), tels que struct, enum et tuple, sont généralement placés sur la pile, tandis que les types de référence (reference types), tels que class, sont placés dans le tas (heap).
L'allocation sur la pile est rapide, automatique et utilisée pour stocker des variables locales ayant une durée de vie courte. L'allocation sur le tas nécessite des coûts supplémentaires et est utilisée pour des objets ayant une durée de vie ou une taille indéfinies.
Exemple:
struct Point { var x: Int; var y: Int } let p1 = Point(x: 2, y: 3) // Sur la pile class Node { var value: Int; init(value: Int) { self.value = value } } let n1 = Node(value: 5) // Dans le tas
Nuances :
Performance : L'allocation sur la pile est plus rapide, car elle ne nécessite pas de gestion de la mémoire dans le tas et de la gestion de la durée de vie des objets.
Tous les structures (struct) sont-elles toujours uniquement placées sur la pile ?
Réponse :
Non ! Bien que les structures soient des types de valeur et qu'elles soient souvent placées sur la pile, le compilateur peut les placer dans le tas si elles se trouvent à l'intérieur d'un objet de classe, d'un tableau, d'un dictionnaire ou sont utilisées comme valeur capturée dans un closure. Par exemple :
class Box { var point: Point init(point: Point) { self.point = point } } let box = Box(point: Point(x: 1, y: 2))
Ici, l'instance Point sera stockée dans le tas, car elle appartient à la classe Box.
Histoire
Un développeur a essayé d'optimiser les performances des structures, pensant que des structures volumineuses seraient toujours dans la pile, sans tenir compte du fait que les collections (Array, Dictionary) utilisent l'allocation sur le tas, ce qui a conduit à une augmentation inattendue de l'utilisation de la mémoire dans le projet.
Histoire
Dans le projet, il n'a pas été pris en compte que le closure capture la valeur de la structure, qui se retrouve dans le tas, influençant la durée de vie de l'objet. Cela a augmenté la durée de vie des variables et a conduit à des fuites de mémoire, car on s'attendait à un relâchement automatique lors de la sortie de portée.
Histoire
L'utilisation de tableaux de structures lourdes sans comprendre copy-on-write a conduit à des opérations de copie coûteuses en raison du transfert de collections entre les threads, diminuant les performances et provoquant des latences dans l'interface utilisateur.