Site icon AppTractor

Вопросы с собеседований: Что такое ARC (Automatic Reference Counting)

ARC (Automatic Reference Counting) — это механизм управления памятью в языке программирования Swift, который автоматически отслеживает и управляет использованием памяти для объектов. ARC отслеживает количество ссылок на объект и автоматически освобождает память, когда объект больше не имеет ни одной ссылки на него.

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

Механизм основан на принципе «подсчета ссылок». Он позволяет разработчикам сосредоточиться на написании кода, а ARC берет на себя ответственность за управление памятью. Это снижает вероятность утечек памяти и упрощает процесс разработки приложений.

На каком этапе работает ARC

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

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

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

Что делает ARC на этапе компиляции

На этапе компиляции ARC в Swift генерирует инструкции для управления памятью, которые встраиваются непосредственно в скомпилированный код. В частности, ARC определяет, когда должны быть добавлены инструкции для увеличения или уменьшения счетчика ссылок на объекты.

При написании кода на Swift вы можете использовать ключевые слова strong, weak и unowned для явного указания типа ссылки и тем самым контроля над тем, как ARC управляет памятью для объектов.

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

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

ARC в действии

Вот пример того, как работает автоматический подсчет ссылок. Этот пример начинается с простого класса Person, в котором определено хранимое константное свойство name:

class Person {
    let name: String
    init(name: String) {
        self.name = name
        print("\(name) is being initialized")
    }
    deinit {
        print("\(name) is being deinitialized")
    }
}

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

В следующем фрагменте кода определяются три переменные типа Person?, которые используются для установки нескольких ссылок на новый экземпляр Person в последующих фрагментах кода. Поскольку эти переменные имеют необязательный тип (Person?, а не Person), они автоматически инициализируются значением nil и в данный момент не ссылаются на экземпляр Person.

var reference1: Person?
var reference2: Person?
var reference3: Person?

Теперь вы можете создать новый экземпляр Person и назначить его одной из этих трех переменных:

reference1 = Person(name: "John Appleseed")
// Prints "John Appleseed is being initialized"

Обратите внимание, что сообщение «John Appleseed is being initialized» выводится в тот момент, когда вы вызываете инициализатор класса Person. Это подтверждает, что инициализация произошла.

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

Если вы присвоите один и тот же экземпляр Person еще двум переменным, будет создано еще две сильные ссылки на этот экземпляр:

reference2 = reference1
reference3 = reference1

Теперь существует три сильные ссылки на этот единственный экземпляр Person.

Если разрушить две из этих сильных ссылок (включая исходную ссылку), присвоив двум переменным nil, останется одна сильная ссылка, и экземпляр Person не будет деаллоцирован:

reference1 = nil
reference2 = nil

Система не удаляет экземпляр Person до тех пор, пока не будет разрушена третья и последняя сильная ссылка, после чего становится ясно, что вы больше не используете экземпляр Person:

reference3 = nil
// Prints "John Appleseed is being deinitialized"

Дополнительно

Exit mobile version