Tampaknya ada pergeseran bertahap dalam berpikir tentang penggunaan pointer dalam bahasa pemrograman sehingga menjadi diterima secara umum bahwa pointer dianggap berisiko (jika tidak langsung "jahat" atau peningkatan yang serupa).
Apa perkembangan historis untuk pergeseran pemikiran ini? Adakah acara khusus, seminar, penelitian, atau perkembangan lainnya?
Sebagai contoh, tampilan dangkal pada transisi dari C ke C ++ ke Java tampaknya menunjukkan tren untuk melengkapi dan kemudian sepenuhnya mengganti pointer dengan referensi. Namun rantai kejadian sebenarnya mungkin jauh lebih halus & kompleks daripada ini, dan tidak begitu berurutan. Fitur-fitur yang membuatnya menjadi bahasa utama tersebut mungkin berasal dari tempat lain, mungkin jauh sebelumnya.
Catatan: Saya tidak bertanya tentang manfaat sebenarnya dari pointer vs referensi vs sesuatu yang lain. Fokus saya adalah pada alasan untuk perubahan yang tampak ini.
Jawaban:
Alasannya adalah pengembangan alternatif untuk pointer.
Di bawah tenda, setiap pointer / referensi / dll sedang diimplementasikan sebagai integer yang berisi alamat memori (alias pointer). Ketika C keluar, fungsi ini diekspos sebagai pointer. Ini berarti bahwa apa pun yang dapat dilakukan perangkat keras yang mendasar untuk mengatasi memori dapat dilakukan dengan pointer.
Ini selalu "berbahaya," tetapi bahaya itu relatif. Saat Anda membuat program 1000 garis, atau ketika Anda memiliki prosedur kualitas perangkat lunak tingkat IBM, bahaya ini dapat dengan mudah diatasi. Namun, tidak semua perangkat lunak dikembangkan dengan cara itu. Dengan demikian, keinginan untuk struktur yang lebih sederhana muncul.
Jika Anda berpikir tentang itu,
int&
danint* const
benar-benar memiliki tingkat keamanan yang sama, tetapi satu memiliki sintaks yang jauh lebih baik daripada yang lain.int&
bisa juga lebih efisien karena bisa merujuk ke int yang disimpan dalam register (anakronisme: ini benar di masa lalu, tetapi kompiler modern sangat baik dalam mengoptimalkan sehingga Anda dapat memiliki pointer ke integer dalam register, selama Anda tidak pernah menggunakan salah satu fitur yang memerlukan alamat aktual, seperti++
)Saat kami pindah ke Jawa , kami pindah ke bahasa yang memberikan jaminan keamanan. C dan C ++ tidak tersedia. Java menjamin bahwa hanya operasi hukum yang dapat dijalankan. Untuk melakukan ini, java menghilangkan pointer sepenuhnya. Apa yang mereka temukan adalah bahwa sebagian besar operasi pointer / referensi dilakukan dalam kode nyata adalah hal-hal yang lebih dari cukup untuk referensi. Hanya dalam beberapa kasus (seperti iterasi cepat melalui array) yang benar-benar diperlukan pointer. Dalam kasus tersebut, java mengambil hit runtime untuk menghindari menggunakannya.
Langkah itu tidak monoton. C # diperkenalkan kembali pointer, meskipun dalam bentuk yang sangat terbatas. Mereka ditandai sebagai " tidak aman ," yang berarti mereka tidak dapat digunakan oleh kode yang tidak dipercaya. Mereka juga memiliki aturan eksplisit tentang apa yang mereka bisa dan tidak bisa tunjukkan (misalnya, itu hanya tidak valid untuk menambah pointer melewati akhir array). Namun, mereka menemukan ada beberapa kasus di mana kinerja tinggi dari pointer diperlukan, jadi mereka memasukkannya kembali.
Yang juga menarik adalah bahasa fungsional, yang tidak memiliki konsep seperti itu sama sekali, tapi itu diskusi yang sangat berbeda.
sumber
Beberapa jenis tipuan diperlukan untuk program yang kompleks (misalnya struktur data rekursif atau berukuran variabel). Namun, tidak perlu menerapkan tipuan ini melalui pointer.
Mayoritas bahasa pemrograman tingkat tinggi (yaitu bukan Majelis) cukup aman-memori dan melarang akses pointer tidak terbatas. Keluarga C adalah yang aneh di sini.
C berevolusi dari B yang merupakan abstraksi yang sangat tipis pada perakitan mentah. B memiliki satu tipe: kata. Kata tersebut dapat digunakan sebagai integer atau sebagai pointer. Keduanya setara ketika seluruh memori dipandang sebagai array yang berdekatan. C menyimpan pendekatan yang agak fleksibel ini dan terus mendukung aritmatika pointer yang secara inheren tidak aman. Seluruh sistem tipe C lebih merupakan sebuah renungan. Fleksibilitas terhadap akses memori ini menjadikan C sangat cocok untuk tujuan utamanya: membuat prototip sistem operasi Unix. Tentu saja Unix dan C ternyata cukup populer, sehingga C juga digunakan dalam aplikasi di mana pendekatan tingkat rendah terhadap memori ini tidak terlalu dibutuhkan.
Jika kita melihat bahasa pemrograman yang datang sebelum C (misalnya Fortran, dialek Algol termasuk Pascal, Cobol, Lisp, ...) beberapa dari mereka mendukung pointer mirip-C. Khususnya, konsep penunjuk nol diciptakan untuk Algol W pada tahun 1965. Tetapi tidak satu pun dari bahasa tersebut yang mencoba menjadi bahasa sistem abstraksi rendah seperti C, efisien, dan Fortran dimaksudkan untuk komputasi ilmiah, Algol mengembangkan beberapa konsep yang cukup maju, Lisp mengembangkan lebih dari proyek penelitian daripada bahasa tingkat industri, dan Cobol berfokus pada aplikasi bisnis.
Pengumpulan sampah sudah ada sejak akhir 50-an, yaitu jauh sebelum C (awal 70-an). GC membutuhkan keamanan memori agar berfungsi dengan benar. Bahasa sebelum dan sesudah C menggunakan GC sebagai fitur normal. Tentu saja itu membuat bahasa jauh lebih rumit dan mungkin lebih lambat, yang terutama terlihat pada saat mainframe. Bahasa-bahasa GC cenderung berorientasi pada penelitian (misalnya Lisp, Simula, ML) dan / atau membutuhkan workstation yang kuat (mis. Smalltalk).
Dengan komputer yang lebih kecil, komputer yang lebih kuat pada umumnya dan bahasa GC secara khusus menjadi lebih populer. Untuk aplikasi non-real time (dan kadang-kadang bahkan saat itu) GC sekarang merupakan pendekatan yang disukai. Tetapi algoritma GC juga telah menjadi subjek penelitian yang intens. Sebagai alternatif, keamanan memori yang lebih baik tanpa GC juga telah dikembangkan lebih lanjut, terutama dalam tiga dekade terakhir: inovasi penting adalah RAII dan smart pointer di C ++ dan sistem seumur hidup / pemeriksa pinjaman Rust.
Java tidak berinovasi dengan menjadi bahasa pemrograman memori-aman: pada dasarnya mengambil semantik dari bahasa Smalltalk GCed, memori aman dan menggabungkannya dengan sintaks dan mengetik statis C ++. Itu kemudian dipasarkan sebagai C / C ++ yang lebih baik, lebih sederhana. Tapi itu hanya dangkal keturunan C ++. Kurangnya pointer Java berutang lebih banyak pada model objek Smalltalk daripada penolakan model data C ++.
Jadi bahasa "modern" seperti Java, Ruby, dan C # tidak boleh diartikan sebagai mengatasi masalah pointer mentah seperti di C, tetapi harus dilihat sebagai menggambar dari banyak tradisi - termasuk C, tetapi juga dari bahasa yang lebih aman seperti Smalltalk, Simula, atau Lisp.
sumber
Dalam pengalaman saya, pointer telah SELALU menjadi konsep yang menantang bagi banyak orang. Pada tahun 1970, universitas tempat saya kuliah memiliki Burroughs B5500, dan kami menggunakan Extended Algol untuk proyek pemrograman kami. Arsitektur perangkat keras didasarkan pada deskriptor dan beberapa kode di bagian atas kata-kata data. Ini secara eksplisit dirancang untuk membiarkan array menggunakan pointer tanpa diizinkan berjalan keluar dari ujung.
Kami melakukan diskusi kelas yang bersemangat tentang referensi nama vs nilai dan bagaimana array B5500 bekerja. Beberapa dari kami langsung mendapat penjelasan. Yang lain tidak.
Belakangan, agak mengejutkan bahwa perangkat keras itu tidak melindungi saya dari petunjuk pelarian - terutama dalam bahasa assembly. Pada pekerjaan pertama saya setelah lulus, saya membantu memperbaiki masalah dalam sistem operasi. Seringkali satu-satunya dokumentasi yang kami miliki adalah tempat sampah cetak. Saya mengembangkan ketrampilan untuk menemukan sumber pointer melarikan diri di dump memori, jadi semua orang memberikan dump "mustahil" kepada saya untuk mencari tahu. Lebih banyak masalah yang kami miliki disebabkan oleh kesalahan pointer daripada oleh jenis kesalahan lainnya.
Banyak orang yang pernah bekerja sama dengan saya mulai menulis FORTRAN, kemudian pindah ke C, menulis C yang sangat mirip FORTRAN, dan menghindari petunjuk. Karena mereka tidak pernah menginternalisasi pointer dan referensi, Java menimbulkan masalah. Seringkali, sulit untuk memahami bagi programmer FORTRAN bagaimana tugas Obyek benar-benar bekerja.
Bahasa modern telah membuatnya jauh lebih mudah untuk melakukan hal-hal yang membutuhkan pointer "di bawah tenda" sambil menjaga kita aman dari kesalahan ketik dan kesalahan lainnya.
sumber