W Swift typy wartości (typu value), takie jak struct, enum i tuple, zwykle są umieszczane na stosie, podczas gdy typy referencyjne (typu reference), takie jak class, są umieszczane w stercie (heap).
Przydzielanie na stosie jest szybkie, automatyczne i służy do przechowywania zmiennych lokalnych o krótkim czasie życia. Przydzielanie w stercie wymaga dodatkowych kosztów i jest używane dla obiektów o nieokreślonym czasie życia lub rozmiarze.
Przykład:
struct Point { var x: Int; var y: Int } let p1 = Point(x: 2, y: 3) // Na stosie class Node { var value: Int; init(value: Int) { self.value = value } } let n1 = Node(value: 5) // W stercie
Szczegóły:
Wydajność: Przydzielanie na stosie jest szybsze, ponieważ nie wymaga pracy z pamięcią w stercie i zarządzania czasem życia obiektów.
Czy wszystkie struktury (struct) zawsze są umieszczane wyłącznie na stosie?
Odpowiedź:
Nie! Chociaż struktury są typami wartości i często są umieszczane na stosie, kompilator może przechowywać je w stercie, jeśli znajdują się wewnątrz obiektu klasy, tablicy, słownika lub są używane jako captured value w closure. Na przykład:
class Box { var point: Point init(point: Point) { self.point = point } } let box = Box(point: Point(x: 1, y: 2))
Tutaj instancja Point będzie przechowywana w stercie, ponieważ należy do klasy Box.
Historia
Programista próbował zoptymalizować wydajność struktur, sądząc, że duże struktury zawsze będą przechowywane na stosie, i nie brał pod uwagę, że kolekcje (Array, Dictionary) używają przydzielania w stercie, co doprowadziło do nieoczekiwanego wzrostu zużycia pamięci w projekcie.
Historia
W projekcie nie uwzględniono, że closure przechwytuje wartość struktury, która trafia do sterty, wpływając na czas życia obiektu. To zwiększyło czas życia zmiennych i doprowadziło do wycieków pamięci, ponieważ oczekiwano automatycznego zwolnienia po wyjściu ze zasięgu.
Historia
Użycie tablic ciężkich struktur bez zrozumienia copy-on-write doprowadziło do nieoczekiwanie drogich operacji kopiowania w wyniku przekazywania kolekcji między wątkami, obniżając wydajność i powodując opóźnienia w UI.