Какие типы данных относятся к стеку, а какие к куче
Что проверяют
Знаете ли вы, как Swift на самом деле размещает value и reference types, или повторяете формулу «структуры на стеке, классы в куче». Следом почти всегда спрашивают про copy-on-write у Array и про то, почему захват в замыкании переносит переменную в кучу.
Как отвечать
Начните с деления типов, а не областей памяти:
- value types:
struct,enum, кортежи, а такжеInt,Double,Bool,String,Array,Dictionary,Set. Копируются при присваивании; - reference types:
class,actor, замыкания. Переменная хранит ссылку, объект живёт в куче, временем жизни управляет ARC через счётчик ссылок.
Дальше честная оговорка: значение хранится там, где объявлено. Локальная структура обычно лежит на стеке, но структура в свойстве класса живёт внутри объекта в куче. Value type тоже попадает в кучу, когда:
- у коллекции есть буфер:
Array,String,Dictionaryсами по себе маленькие структуры, а элементы держат в куче и копируют лениво, по copy-on-write; - переменную захватило замыкание: захваченная
varупаковывается в кучу, чтобы пережить выход из функции; - значение спрятано за протоколом:
any Shapeлежит в экзистенциальном контейнере с буфером на три машинных слова, крупные структуры уходят в кучу; - есть
indirect enum: рекурсивный кейс хранится в отдельной ячейке кучи.
Обратное тоже бывает: если объект класса не покидает функцию, оптимизатор может разместить его на стеке.
Почему это важно: выделение на стеке это сдвиг указателя, а куча требует аллокации и атомарных retain/release. Поэтому в горячем коде структуры обычно выигрывают, а some Protocol и дженерики обходятся дешевле, чем any.
Где спотыкаются
Называют сборщик мусора. В Swift его нет, есть ARC, и отсюда циклы сильных ссылок, которые разрывают через weak и unowned.
Утверждают, что Array копируется целиком при каждом присваивании. Буфер копируется только при первой записи в массив, который делят несколько переменных.
Считают, что структура всегда быстрее класса. Большая структура с десятком ссылочных полей при каждом копировании делает retain для каждого из них и может проиграть классу.