ARC est juste un ancien jeu de retenue / libération (MRC) avec le compilateur qui détermine quand appeler la conservation / libération. Il aura tendance à avoir des performances plus élevées, une utilisation maximale de la mémoire de pointe et des performances plus prévisibles qu'un système GC.
En revanche, certains types de structure de données ne sont pas possibles avec ARC (ou MRC), tandis que GC peut les gérer.
Par exemple, si vous avez une classe nommée node et que node a un NSArray d'enfants et une seule référence à son parent qui "fonctionne" avec GC. Avec ARC (et le comptage manuel des références également), vous avez un problème. Tout nœud donné sera référencé à partir de ses enfants et également de son parent.
Comme:
A -> [B1, B2, B3]
B1 -> A, B2 -> A, B3 -> A
Tout va bien lorsque vous utilisez A (disons via une variable locale).
Lorsque vous en aurez terminé (et B1 / B2 / B3), un système GC décidera éventuellement de regarder tout ce qu'il peut trouver à partir de la pile et des registres CPU. Il ne trouvera jamais A, B1, B2, B3, il les finalisera donc et recyclera la mémoire en d'autres objets.
Lorsque vous utilisez ARC ou MRC et que vous finissez avec A, il a un décompte de 3 (B1, B2 et B3 le référencent tous), et B1 / B2 / B3 aura tous un décompte de référence de 1 (le NSArray de A contient une référence à chaque). Tous ces objets restent donc vivants même si rien ne peut jamais les utiliser.
La solution courante consiste à décider que l'une de ces références doit être faible (ne pas contribuer au décompte des références). Cela fonctionnera pour certains modèles d'utilisation, par exemple si vous référencez B1 / B2 / B3 uniquement via A. Cependant, dans d'autres modèles, cela échoue. Par exemple, si vous vous accrocherez parfois à B1 et que vous vous attendez à remonter via le pointeur parent et à trouver A. Avec une référence faible si vous ne maintenez que B1, A peut (et normalement va) s'évaporer et prendre B2 et B3 avec ça.
Parfois, ce n'est pas un problème, mais certaines façons très utiles et naturelles de travailler avec des structures de données complexes sont très difficiles à utiliser avec ARC / MRC.
L'ARC cible donc le même type de problèmes que le GC cible. Cependant, ARC fonctionne sur un ensemble de modèles d'utilisation plus limité que GC, donc si vous preniez un langage GC (comme Java) et y greffiez quelque chose comme ARC, certains programmes ne fonctionneraient plus (ou du moins généreraient des tonnes de mémoire abandonnée). et peut entraîner de graves problèmes de permutation ou manquer de mémoire ou d'espace d'échange).
Vous pouvez également dire que l'ARC accorde une plus grande priorité aux performances (ou peut-être à la prévisibilité) tandis que GC accorde une plus grande priorité à une solution générique. Par conséquent, GC a des demandes CPU / mémoire moins prévisibles et des performances (normalement) inférieures à ARC, mais peut gérer n'importe quel modèle d'utilisation. ARC fonctionnera beaucoup mieux pour de nombreux modèles d'utilisation courants, mais pour quelques modèles d'utilisation (valides!), Il tombera et mourra.