Jawaban sebenarnya adalah bahwa satu-satunya cara untuk membuat mekanisme pengumpulan sampah yang aman dan efisien adalah dengan memiliki dukungan tingkat bahasa untuk referensi yang tidak jelas. (Atau, sebaliknya, kurangnya dukungan tingkat bahasa untuk manipulasi memori langsung.)
Java dan C # dapat melakukannya karena mereka memiliki tipe referensi khusus yang tidak dapat dimanipulasi. Ini memberikan runtime kebebasan untuk melakukan hal-hal seperti memindahkan objek yang dialokasikan dalam memori , yang sangat penting untuk implementasi GC berkinerja tinggi.
Sebagai catatan, tidak ada implementasi GC modern yang menggunakan penghitungan referensi , sehingga benar-benar ikan haring merah. GC modern menggunakan koleksi generasi, di mana alokasi baru diperlakukan pada dasarnya dengan cara yang sama seperti tumpukan alokasi dalam bahasa seperti C ++, dan kemudian secara berkala setiap objek yang baru dialokasikan yang masih hidup dipindahkan ke ruang "selamat" yang terpisah, dan seluruh generasi benda dialokasikan sekaligus.
Pendekatan ini memiliki pro dan kontra: terbalik adalah bahwa tumpukan alokasi dalam bahasa yang mendukung GC secepat alokasi tumpukan dalam bahasa yang tidak mendukung GC, dan downside adalah bahwa objek yang perlu melakukan pembersihan sebelum dihancurkan baik memerlukan mekanisme terpisah (mis. using
kata kunci C # ) atau kode pembersihannya berjalan non-deterministik.
Perhatikan bahwa salah satu kunci untuk GC kinerja tinggi adalah bahwa harus ada dukungan bahasa untuk kelas referensi khusus. C tidak memiliki dukungan bahasa ini dan tidak akan pernah; karena C ++ memiliki overloading operator, ini dapat mengemulasi tipe pointer GC, meskipun itu harus dilakukan dengan hati-hati. Bahkan, ketika Microsoft menemukan dialek C ++ yang akan berjalan di bawah CLR (.NET runtime), mereka harus menciptakan sintaks baru untuk "referensi gaya C #" (mis. Foo^
) Untuk membedakan mereka dari "referensi gaya C ++" (mis Foo&
.).
Apa yang dimiliki C ++, dan apa yang secara teratur digunakan oleh para programmer C ++, adalah pointer cerdas , yang sebenarnya hanyalah mekanisme penghitungan referensi. Saya tidak akan menganggap penghitungan referensi sebagai GC "benar", tetapi memberikan banyak manfaat yang sama, dengan biaya kinerja yang lebih lambat daripada manajemen memori manual atau GC benar, tetapi dengan keuntungan dari kerusakan deterministik.
Pada akhirnya, jawabannya benar-benar bermuara pada fitur desain bahasa. C membuat satu pilihan, C ++ membuat pilihan yang memungkinkannya kompatibel dengan C sambil tetap memberikan alternatif yang cukup baik untuk sebagian besar tujuan, dan Java dan C # membuat pilihan lain yang tidak kompatibel dengan C tetapi juga cukup baik untuk sebagian besar tujuan. Sayangnya, tidak ada peluru perak, tetapi terbiasa dengan berbagai pilihan di luar sana akan membantu Anda memilih yang benar untuk program apa pun yang sedang Anda coba buat.