La vraie réponse est que le seul moyen de créer un mécanisme de collecte des ordures sûr et efficace consiste à prendre en charge les références opaques au niveau de la langue . (Ou, inversement, un manque de prise en charge au niveau de la langue pour la manipulation directe de la mémoire.)
Java et C # peuvent le faire car ils ont des types de référence spéciaux qui ne peuvent pas être manipulés. Cela donne au moteur d'exécution la liberté de déplacer des objets alloués en mémoire , ce qui est essentiel pour une implémentation GC haute performance.
Pour mémoire, aucune implémentation moderne du GC n’utilise le comptage de références , ce qui en fait un véritable casse-tête. Les GC modernes utilisent la collection générationnelle, où les nouvelles allocations sont traitées essentiellement de la même manière que les allocations de pile dans un langage tel que C ++, puis tous les objets nouvellement alloués encore en vie sont déplacés vers un espace "survivant" séparé et une génération entière. des objets est désalloué à la fois.
Cette approche a des avantages et des inconvénients: l'avantage réside dans le fait que les allocations de segment de mémoire dans un langage prenant en charge le GC sont aussi rapides que les allocations de pile dans un langage ne prenant pas en charge le GC, et l'inconvénient est que les objets devant être nettoyés avant d'être détruits besoin d' un mécanisme distinct (par exemple C de # using
mot - clé) ou bien leur code de nettoyage fonctionne non déterministe.
Notez que l'une des clés d'un CPG hautes performances est la prise en charge linguistique d'une classe de références spécifique. C n'a pas cette langue et ne le fera jamais; Comme C ++ a une surcharge d'opérateur, il pourrait émuler un type de pointeur GC, bien que cela devrait être fait avec précaution. En fait, lorsque Microsoft a inventé son dialecte C ++ qui s'exécutait sous le CLR (le runtime .NET), il a fallu inventer une nouvelle syntaxe pour "références de style C #" (par exemple Foo^
) afin de les distinguer des "références de style C ++". (par exemple Foo&
).
Ce que C ++ a, et que les programmeurs C ++ utilisent régulièrement , ce sont des pointeurs intelligents , qui ne sont en réalité qu'un mécanisme de comptage de références. Je ne considérerais pas le comptage de références comme un "vrai" GC, mais il offre bon nombre des mêmes avantages, au détriment des performances plus lentes que la gestion manuelle de la mémoire ou le véritable GC, mais avec l’avantage de la destruction déterministe.
À la fin de la journée, la réponse se résume vraiment à une fonctionnalité de conception de langage. C a fait un choix, C ++ a fait un choix qui lui a permis d’être rétro-compatible avec le C tout en offrant des alternatives assez bonnes pour la plupart des applications, et Java et C # ont fait un choix différent, incompatible avec le C, mais également suffisant pour la plupart des fins. Malheureusement, il n’ya pas de solution miracle, mais connaître les différents choix qui s’offrent à vous vous aidera à choisir celui qui convient le mieux au programme que vous essayez de créer.