ARC - это просто старое сохранение / освобождение (MRC), а компилятор выясняет, когда вызывать сохранение / освобождение. Он будет иметь более высокую производительность, более низкое пиковое использование памяти и более предсказуемую производительность, чем система GC.
С другой стороны, некоторые типы структуры данных невозможны с ARC (или MRC), в то время как GC может обрабатывать их.
Например, если у вас есть класс с именем node, а node имеет NSArray дочерних элементов и единственная ссылка на его родительский элемент, который «просто работает» с GC. С ARC (и ручным подсчетом ссылок) у вас есть проблема. На любой данный узел будут ссылаться его дочерние элементы, а также родительские элементы.
Подобно:
A -> [B1, B2, B3]
B1 -> A, B2 -> A, B3 -> A
Все в порядке, пока вы используете A (скажем, через локальную переменную).
Когда вы закончите с этим (и B1 / B2 / B3), система GC в конечном итоге решит взглянуть на все, что может найти, начиная со стека и регистров процессора. Он никогда не найдет A, B1, B2, B3, поэтому он завершит их и переместит память в другие объекты.
Когда вы используете ARC или MRC и заканчиваете буквой A, у него будет повторный счет 3 (B1, B2 и B3 все ссылаются на него), а B1 / B2 / B3 будет иметь счетчик ссылок 1 (NSArray A содержит одну ссылку на каждый). Таким образом, все эти объекты остаются живыми, хотя ничто не может их использовать.
Общее решение состоит в том, чтобы решить, что одна из этих ссылок должна быть слабой (не способствовать подсчету ссылок). Это будет работать для некоторых шаблонов использования, например, если вы ссылаетесь на B1 / B2 / B3 только через A. Однако в других шаблонах это дает сбой. Например, если вы иногда держитесь за B1, и ожидаете подняться вверх через родительский указатель и найдете A. Со слабой ссылкой, если вы только держитесь за B1, A может (и обычно будет) испаряться, и принимать B2, и B3 с этим.
Иногда это не проблема, но некоторые очень полезные и естественные способы работы со сложными структурами данных очень сложно использовать с ARC / MRC.
Таким образом, ARC нацеливается на те же проблемы, что и GC. Однако ARC работает с более ограниченным набором шаблонов использования, чем GC, поэтому, если вы взяли язык GC (например, Java) и привили на него что-то вроде ARC, некоторые программы больше не будут работать (или, по крайней мере, будут генерировать тонны заброшенной памяти). , и может вызвать серьезные проблемы с обменом или нехваткой памяти или места подкачки).
Можно также сказать, что ARC придает большее значение производительности (или, возможно, предсказуемости), в то время как GC придает большее значение универсальному решению. В результате GC имеет менее предсказуемые требования к процессору / памяти и более низкую производительность (обычно), чем ARC, но может обрабатывать любые схемы использования. ARC будет работать намного лучше для многих распространенных шаблонов использования, но для нескольких (действительных!) Шаблонов использования он упадет и умрет.