In Swift, i tipi di valore (value types), come struct, enum e tuple, vengono solitamente allocati nello stack, mentre i tipi di riferimento (reference types), come class, sono allocati nell'heap.
Stack allocation è veloce, automatica e utilizzata per memorizzare variabili locali con una vita breve. Heap allocation richiede costi aggiuntivi ed è utilizzata per oggetti con una durata di vita indefinita o una dimensione maggiore.
Esempio:
struct Point { var x: Int; var y: Int } let p1 = Point(x: 2, y: 3) // Nello stack class Node { var value: Int; init(value: Int) { self.value = value } } let n1 = Node(value: 5) // Nell'heap
Nuggets:
Prestazioni: L'allocazione nello stack è più veloce poiché non richiede operazioni di gestione della memoria nell'heap e controllo della vita degli oggetti.
Tutte le struct (struct) sono sempre allocate esclusivamente nello stack?
Risposta:
No! Anche se le struct sono value types e sono spesso allocate nello stack, il compilatore può allocarle nell'heap se si trovano all'interno di un oggetto classe, di un array, di un dizionario o se usate come captured value in una closure. Ad esempio:
class Box { var point: Point init(point: Point) { self.point = point } } let box = Box(point: Point(x: 1, y: 2))
Qui l'istanza Point sarà memorizzata nell'heap poiché appartiene alla classe Box.
Storia
Un sviluppatore stava tentando di ottimizzare le prestazioni delle struct, pensando che le struct grandi sarebbero sempre state allocate nello stack, senza considerare che le collezioni (Array, Dictionary) utilizzano l'allocazione nell'heap, portando a un inatteso aumento dei costi di memoria nel progetto.
Storia
Nel progetto non si considerava che la closure cattura il valore della struct, che finisce nell'heap, influenzando il tempo di vita dell'oggetto. Ciò ha aumentato il tempo di vita delle variabili e ha portato a perdite di memoria, poiché ci si aspettava un rilascio automatico al di fuori dello scope.
Storia
L'uso di array di struct pesanti senza comprendere copy-on-write ha portato a costose operazioni di copia a causa della trasmissione delle collezioni tra i thread, riducendo le prestazioni e causando ritardi nell'interfaccia utente.