Saya membaca dari suatu tempat bahwa ketika menggunakan C ++ disarankan untuk tidak menggunakan pointer. Mengapa pointer adalah ide yang buruk ketika Anda menggunakan C ++. Untuk programmer C yang terbiasa menggunakan pointer, apa alternatif dan pendekatan yang lebih baik dalam C ++?
45
NetConnection
instances disconnecting from the server (stackoverflow.com/questions/14780456/…), as well as an issue with there being multiple objects in a program that it will specifically refuse to ever collect ...GCRoots are never garbage collected.
dan paragraf dimulai denganThe MMgc is considered a conservative collector for mark/sweep.
). Secara teknis ini adalah masalah di Adobe Virtual Machine 2, bukan AS3 itu sendiri, tetapi ketika Anda memiliki masalah seperti ini dalam bahasa tingkat yang lebih tinggi, yang pada dasarnya memiliki pengumpulan sampah, Anda sering tidak memiliki cara yang benar dalam bahasa untuk melakukan debug masalah ini sepenuhnya keluar dari program. ...Jawaban:
Saya pikir mereka berarti Anda harus menggunakan pointer pintar daripada pointer biasa.
Dalam C ++ penekanannya akan pada pengumpulan sampah dan mencegah kebocoran memori (hanya untuk menyebutkan dua). Pointer adalah bagian mendasar dari bahasa, jadi tidak menggunakannya sama sekali tidak mungkin kecuali dalam program yang paling trival.
sumber
Karena saya orang yang menerbitkan polemik “jangan gunakan pointer f * cking” saya merasa bahwa saya harus berkomentar di sini.
Pertama-tama, sebagai polemik, ini jelas mewakili sudut pandang ekstrem. Jelas ada penggunaan sah dari pointer (mentah). Tetapi saya (dan banyak programmer C ++ profesional) berpendapat bahwa kasus-kasus ini sangat jarang. Tapi yang kami maksud adalah:
Pertama:
Di sini, "memori sendiri" pada dasarnya berarti bahwa pada titik tertentu
delete
disebut pada pointer itu (tetapi lebih umum dari itu). Pernyataan ini dapat dengan aman dianggap mutlak. Satu- satunya pengecualian adalah ketika menerapkan smart pointer Anda sendiri (atau strategi manajemen memori lainnya). Dan bahkan di sana Anda biasanya harus tetap menggunakan smart pointer di level rendah.Alasan untuk ini cukup sederhana: pointer mentah yang memiliki memori memperkenalkan sumber kesalahan. Dan kesalahan ini banyak terjadi pada perangkat lunak yang ada: kebocoran memori dan penghapusan ganda - keduanya merupakan konsekuensi langsung dari kepemilikan sumber daya yang tidak jelas (tetapi berlawanan arah).
Masalah ini dapat sepenuhnya dihilangkan, hampir tanpa biaya, dengan hanya menggunakan pointer pintar bukan pointer mentah (peringatan: ini masih membutuhkan pemikiran, tentu saja; pointer bersama dapat menyebabkan siklus dan dengan demikian sekali lagi ke kebocoran memori - tetapi ini dengan mudah dihindari).
Kedua:
Tidak seperti bahasa lain, C ++ memiliki dukungan yang sangat kuat untuk semantik nilai dan tidak perlu tipuan pointer. Ini tidak segera terwujud - secara historis, C ++ ditemukan untuk memfasilitasi orientasi objek yang mudah dalam C, dan sangat bergantung pada pembuatan grafik objek yang dihubungkan oleh pointer. Tetapi dalam C ++ modern, paradigma ini jarang merupakan pilihan terbaik, dan idiom C ++ modern seringkali tidak memerlukan pointer sama sekali . Mereka beroperasi pada nilai daripada pointer.
Sayangnya, pesan ini masih belum tertangkap di sebagian besar komunitas pengguna C ++. Akibatnya, sebagian besar kode C ++ yang ditulis masih dikotori dengan pointer berlebihan yang membuat kode kompleks, lambat dan rusak / tidak dapat diandalkan.
Untuk seseorang yang tahu C yang modern ++, jelas bahwa Anda sangat jarang perlu setiap pointer (baik pintar atau mentah; kecuali bila menggunakan mereka sebagai iterator). Kode yang dihasilkan lebih pendek, kurang kompleks, lebih mudah dibaca, seringkali lebih efisien dan lebih dapat diandalkan.
sumber
std::unique_ptr
. Kenapa tidakptr_vec
? Tetapi biasanya vektor nilai dengan masih akan bertukar lebih cepat (terutama dengan memindahkan semantik).boost::variant
denganrecursive_wrapper
mungkin solusi favorit saya untuk mewakili DAG.Hanya karena ada abstraksi yang tersedia untuk Anda yang menyembunyikan aspek yang lebih temperamental menggunakan pointer, seperti akses ke memori mentah dan membersihkan setelah alokasi Anda. Dengan pointer cerdas, kelas wadah, dan pola desain seperti RAII, kebutuhan untuk menggunakan pointer mentah berkurang. Yang mengatakan, seperti abstraksi apa pun, Anda harus memahami bagaimana mereka benar-benar bekerja sebelum bergerak melampaui mereka.
sumber
Relatif sederhana, mentalitas C adalah "Punya masalah? Gunakan pointer". Anda dapat melihat ini dalam string C, pointer fungsi, pointer-sebagai-iterator, pointer-to-pointer, void pointer- bahkan pada hari-hari awal C ++ dengan pointer anggota.
Tetapi dalam C ++ Anda bisa menggunakan nilai untuk banyak atau semua tugas ini. Perlu abstraksi fungsi?
std::function
. Ini adalah nilai yang berfungsi.std::string
? Ini sebuah nilai, itu sebuah string. Anda dapat melihat pendekatan serupa di seluruh C ++. Ini membuat menganalisis kode jauh lebih mudah bagi manusia dan penyusun.sumber
Salah satu alasannya adalah penerapan pointer yang terlalu luas. Mereka dapat digunakan untuk iterasi di atas wadah, untuk menghindari penyalinan benda besar saat beralih ke fungsi, manajemen seumur hidup non-sepele, mengakses ke tempat-tempat acak dalam memori, dll. Dan begitu Anda menggunakannya untuk satu tujuan, fitur-fitur lainnya akan tersedia segera secara mandiri dengan sengaja.
Pemilihan alat untuk tujuan yang tepat membuat kode lebih mudah dan maksud lebih terlihat - iterator untuk iterasi, pointer pintar untuk manajemen seumur hidup, dll.
sumber
Selain alasan yang sudah disebutkan, ada alasan yang jelas: optimisasi yang lebih baik. Analisis aliasing terlalu rumit dalam hal aritmatika penunjuk, sedangkan referensi mengisyaratkan pengoptimal, sehingga analisis aliasing jauh lebih dalam dimungkinkan jika hanya referensi yang digunakan.
sumber
Selain risiko kebocoran memori yang dinyatakan oleh pointer @jmquigley dan aritmatika pointer dapat dianggap bermasalah karena pointer dapat menunjukkan di mana-mana dalam memori yang menyebabkan "sulit menemukan bug" dan "kerentanan keamanan".
Itulah sebabnya mereka hampir ditinggalkan di C # dan Java.
sumber
unsafe
kata kunciC ++ mendukung sebagian besar C , fitur, plus Objek dan Kelas. C sudah memiliki petunjuk dan hal-hal lainnya.
Pointer adalah teknik yang sangat berguna, yang dapat dikombinasikan dengan Orientasi Objek, dan C ++ mendukungnya. Tapi, teknik ini, sulit diajarkan dan sulit dipahami, dan, sangat mudah menyebabkan kesalahan yang tidak diinginkan.
Banyak bahasa pemrograman baru berpura-pura tidak menggunakan pointer dengan objek, seperti Java, .NET, Delphi, Vala, PHP, Scala. Tapi, pointer masih digunakan, "di belakang layar". Teknik "pointer tersembunyi" ini disebut "referensi".
Bagaimanapun, saya menganggap pointer sebagai Pola Pemrograman, sebagai cara yang valid untuk memecahkan masalah tertentu, serta Pemrograman Berorientasi Objek tidak.
Pengembang lain mungkin memiliki pendapat berbeda. Tapi, saya sarankan siswa dan programmer belajar bagaimana:
(1) Gunakan pointer tanpa objek
(2) objek tanpa pointer
(3) pointer eksplisit ke objek
(4) pointer "tersembunyi" ke objek ( referensi AKA ) ;-)
Dalam urutan itu.
Kalaupun sulit untuk diajar, dan sulit untuk dipelajari. Obyek Pascal (Delphi, FreePascal, lainnya) dan
C++
(bukan Java atau C #) dapat digunakan untuk tujuan tersebut.Dan, nantinya, programmer pemula, dapat pindah ke "pointer tersembunyi ke objek" bahasa pemrograman seperti: Java, C #, PHP Berorientasi Objek, dan lainnya.
sumber
Berbicara tentang VC6, ketika Anda melemparkan pointer kelas (yang Anda instantiate) ke dalam variabel (misalnya DWORD), bahkan jika pointer ini lokal Anda dapat mengakses kelas atas semua fungsi yang menggunakan tumpukan yang sama. Kelas instantiated didefinisikan sebagai lokal tetapi sebenarnya tidak. Sejauh yang saya tahu, alamat variabel, struktur, atau kelas apa pun adalah unik sepanjang umur kelas hosting.
Contoh:
EDIT Itu bagian sangat kecil dari kode asli. Kelas CSRecodset hanya kelas casting CXdbRecordset, di mana semua kode sebenarnya berada. Dengan melakukan itu, saya dapat membiarkan pengguna mengambil manfaat dari apa yang saya tulis tanpa kehilangan hak saya. Saya tidak berpura-pura menunjukkan bahwa mesin basis data saya profesional tetapi benar-benar berfungsi.
EDIT: diminta oleh DeadMG:
sumber
DWORD
kasar dan mungkin salah (DWORD tidak cukup lebar untuk menahan pointer). Jika Anda memerlukan pointer yang tidak diketik, gunakanvoid*
- tetapi ketika Anda membutuhkannya di C ++, Anda sering mendapatkan masalah desain dalam kode yang harus Anda perbaiki.