typography
Value и reference типы
Стек
Когда мы создаем тип значения, такой как структура, система сохраняет его в области памяти, называемой стеком, которая непосредственно управляется и оптимизируется процессором. Когда функция объявляет переменную, переменная будет сохранена в стеке. Когда функция вызывается, стек автоматически освобождает переменную. Таким образом, стек очень прост в управлении и эффективен, поскольку он напрямую управляется процессором, скорость очень высока. Стек использует кэш первого уровня.

Стек — это область оперативной памяти, которая создаётся для каждого потока. Он работает в порядке LIFO (Last In, First Out), то есть последний добавленный в стек кусок памяти будет первым в очереди на вывод из стека. Каждый раз, когда функция объявляет новую переменную, она добавляется в стек, а когда эта переменная пропадает из области видимости (например, когда функция заканчивается), она автоматически удаляется из стека. Когда стековая переменная освобождается, эта область памяти становится доступной для других стековых переменных.

Из-за такой природы стека управление памятью оказывается весьма логичным и простым для выполнения на ЦП; это приводит к высокой скорости, в особенности потому, что время цикла обновления байта стека очень мало, т.е. этот байт скорее всего привязан к кэшу процессора. Тем не менее, у такой строгой формы управления есть и недостатки. Размер стека — это фиксированная величина, и превышение лимита выделенной на стеке памяти приведёт к переполнению стека. Размер задаётся при создании потока, и у каждой переменной есть максимальный размер, зависящий от типа данных. Это позволяет ограничивать размер некоторых переменных (например, целочисленных), и вынуждает заранее объявлять размер более сложных типов данных (например, массивов), поскольку стек не позволит им изменить его. Кроме того, переменные, расположенные на стеке, всегда являются локальными.

В итоге стек позволяет управлять памятью наиболее эффективным образом — но если вам нужно использовать динамические структуры данных или глобальные переменные, то стоит обратить внимание на кучу.

До тех пор, пока размер типа значения известен во время компиляции и он не содержит / не содержится рекурсивно ссылочным типом, ему не потребуется подсчет ссылок, и его срок службы будет статическим - равным сроку службы его области видимости. Он будет полностью выделен в стеке, и когда область будет освобождена, то же самое произойдет и с типом значения. Отсутствие накладных расходов на подсчет ссылок и наличие выделения стека значительно повышают производительность.

Memory Layout - later

Если размер вашего типа значения не может быть определен во время компиляции (из-за протокола / общего требования), или если ваш тип значения рекурсивно содержит / содержится ссылочным типом (помните, что замыкания также являются ссылочными типами), то для этого потребуется выделение кучи. Это может варьироваться от того, что это вообще не проблема, до того, что ваша структура будет работать экспоненциально хуже, чем если бы это был класс.

Тип значения, полностью выделенный стеком, не нуждается в подсчете ссылок, но тип значения с внутренними ссылками, к сожалению, унаследует эту способность.

Поскольку все ссылочные типы требуют подсчета ссылок, увеличение количества свойств класса классов не изменит время выполнения этого алгоритма, поскольку простого увеличения количества ссылок родительской ссылки будет достаточно, чтобы сохранить его внутренние ссылки живыми.

Однако типы значений, естественно, не имеют подсчета ссылок. Если ваш тип значения содержит внутренние ссылки, для его копирования потребуется увеличить количество ссылок на его дочерние элементы - не на первый, не на второй, а буквально на каждый из них.
Куча
Когда мы создаем ссылочный тип, такой как класс, система сохраняет экземпляр класса в области памяти, называемой кучей. Система использует кучу для хранения данных, на которые ссылаются другие объекты.
Куча - это большой пул памяти, из которого система может запрашивать и динамически выделять блоки памяти.

Куча — это хранилище памяти, также расположенное в ОЗУ, которое допускает динамическое выделение памяти и не работает по принципу стека: это просто склад для ваших переменных. Когда вы выделяете в куче участок памяти для хранения переменной, к ней можно обратиться не только в потоке, но и во всем приложении. Именно так определяются глобальные переменные. По завершении приложения все выделенные участки памяти освобождаются. Размер кучи задаётся при запуске приложения, но, в отличие от стека, он ограничен лишь физически, и это позволяет создавать динамические переменные.

Вы взаимодействуете с кучей посредством ссылок, обычно называемых указателями — это переменные, чьи значения являются адресами других переменных. Создавая указатель, вы указываете на местоположение памяти в куче, что задаёт начальное значение переменной и говорит программе, где получить доступ к этому значению. Из-за динамической природы кучи ЦП не принимает участия в контроле над ней; в языках без сборщика мусора (C, C++) разработчику нужно вручную освобождать участки памяти, которые больше не нужны. Если этого не делать, могут возникнуть утечки и фрагментация памяти, что существенно замедлит работу кучи.

В сравнении со стеком, куча работает медленнее, поскольку переменные разбросаны по памяти, а не сидят на верхушке стека. Некорректное управление памятью в куче приводит к замедлению её работы; тем не менее, это не уменьшает её важности — если вам нужно работать с динамическими или глобальными переменными, пользуйтесь кучей.
Заключение
Вот вы и познакомились с понятиями стека и кучи. Вкратце, стек — это очень быстрое хранилище памяти, работающее по принципу LIFO и управляемое процессором. Но эти преимущества приводят к ограниченному размеру стека и специальному способу получения значений. Для того, чтобы избежать этих ограничений, можно пользоваться кучей — она позволяет создавать динамические и глобальные переменные — но управлять памятью должен либо сборщик мусора, либо сам программист, да и работает куча медленнее.

Куча хранится во вторичном кэше, а ее жизненный цикл определяется алгоритмом сборки мусора виртуальной машины (не один раз потерянные объекты могут быть переработаны). Таким образом, скорость вызова этих объектов относительно невелика.

Указатель в стеке - это просто целочисленная переменная, которая содержит данные определенного адреса памяти в куче. Короче говоря, операционная система использует значение указателя в сегменте стека для доступа к объектам в сегменте кучи. Если нет указателя на объект стека, доступ к объекту в куче невозможен. Это также является причиной утечек памяти.

Вы можете создавать объекты данных как в сегментах стека, так и в куче IOS.
Объект Stack имеет два преимущества, одно из которых заключается в быстром создании, другое - в простом управлении, у него строгий жизненный цикл. Недостатком объекта стека является то, что он негибкий. Пока он создан, он всегда принадлежит функции, которая его создала. В отличие от объекта кучи с несколькими владельцами, несколько владельцев эквивалентны подсчету ссылок. Только объект кучи управляется методом "подсчета ссылок".