Orang-orang yang terbiasa dengan sampah bahasa yang dikumpulkan sering takut dengan manajemen memori C ++. Ada alat, suka auto_ptr
dan shared_ptr
yang akan menangani banyak tugas manajemen memori untuk Anda. Banyak pustaka C ++ mendahului alat-alat itu, dan memiliki cara mereka sendiri untuk menangani tugas manajemen memori.
Berapa banyak waktu yang Anda habiskan untuk tugas manajemen memori?
Saya menduga itu sangat tergantung pada set perpustakaan yang Anda gunakan, jadi tolong katakan yang mana jawaban Anda berlaku, dan jika mereka membuatnya lebih baik atau lebih buruk.
Jawaban:
Modern C ++ membuat Anda tidak perlu khawatir tentang manajemen memori sampai Anda harus melakukannya, yaitu sampai Anda perlu mengatur memori Anda dengan tangan, sebagian besar untuk tujuan optimasi, atau jika konteks memaksa Anda untuk melakukannya (pikirkan perangkat keras kendala besar). Saya telah menulis seluruh permainan tanpa memanipulasi memori mentah, hanya mengkhawatirkan tentang menggunakan wadah yang merupakan alat yang tepat untuk pekerjaan itu, seperti dalam bahasa apa pun.
Jadi itu tergantung pada proyek tetapi sebagian besar waktu itu bukan manajemen memori yang harus Anda tangani tetapi hanya objek seumur hidup. Itu diselesaikan dengan menggunakan smart pointer , yaitu salah satu alat C ++ idiomatik yang dihasilkan dari RAII .
Setelah Anda memahami RAII , manajemen memori tidak akan menjadi masalah.
Maka ketika Anda perlu mengakses memori mentah, Anda akan melakukannya dalam kode yang sangat spesifik, dilokalisasi dan dapat diidentifikasi, seperti dalam implementasi kumpulan objek, bukan "di mana-mana".
Di luar kode semacam ini, Anda tidak perlu memanipulasi memori, hanya objek seumur hidup.
Bagian "sulit" adalah memahami RAII.
sumber
delete
secara manual, kecuali jika Anda memiliki satu implementasi buruk.return
)Manajemen memori digunakan untuk menakuti anak-anak, tetapi hanya satu jenis sumber daya yang harus dijaga oleh seorang programmer. Pikirkan file handle, koneksi jaringan, sumber daya lain yang Anda peroleh dari OS.
Bahasa yang mendukung pengumpulan sampah biasanya tidak hanya mengabaikan keberadaan sumber daya ini, tetapi juga mempersulit penanganannya dengan tidak menyediakan destruktor.
Jadi, singkatnya, saya sarankan tidak banyak waktu pengembang C ++ dihabiskan untuk mengkhawatirkan manajemen memori. Seperti yang ditunjukkan oleh klaim , setelah Anda menguasai RAII, sisanya hanya refleks.
sumber
finalize
konstruk. Namun, Anda tidak tahu kapan akan dipanggil. Apakah itu sebelum Anda kehabisan soket, atau objek WebResponse? Anda akan menemukan banyak artikel yang memberi tahu Anda bahwa Anda tidak boleh mengandalkanfinalize
- dengan alasan yang bagus.Cukup banyak. Bahkan teknologi lama seperti COM, Anda dapat menulis pengubah kustom untuk pointer Standar yang akan mengonversinya dalam waktu yang sangat singkat. Misalnya,
std::unique_ptr
dapat dikonversi untuk secara unik menyimpan referensi COM dengan lima baris deleter khusus. Bahkan jika Anda harus secara manual menulis handler sumber daya Anda sendiri, prevalensi pengetahuan seperti SRP dan copy-and-swap membuatnya relatif mudah untuk menulis kelas pengelola sumber daya agar dapat digunakan selamanya lebih banyak.Kenyataannya adalah bahwa kepemilikan bersama, unik, dan tidak kepemilikan semuanya disertakan bersama kompiler C ++ 11 Anda, dan Anda hanya perlu menulis adaptor kecil untuk membuatnya bekerja bahkan dengan kode lama.
sumber
Ketika saya masih seorang programmer C ++ (lama sekali), saya menghabiskan waktu yang lama khawatir tentang bug manajemen memori ketika mencoba untuk memperbaiki mereproduksi bug .
Dengan modem C ++, manajemen memori jauh lebih sedikit dari masalah, tetapi bisakah Anda memercayai semua orang dalam tim besar untuk memperbaikinya. Berapa biaya / waktu:
Jadi bukan hanya menghabiskan waktu untuk " melakukan ", ini lebih merupakan masalah pada proyek-proyek besar.
sumber
Saya menggunakan boost dan pustaka TR1, dan mereka membuat manajemen memori dalam arti yang ketat (baru / hapus) bukan masalah. Di sisi lain, alokasi memori dalam C ++ tidak murah, dan orang harus memperhatikan di mana pointer bersama mewah ini dibuat. Anda sering menggunakan ruang kerja, atau bekerja dengan memori berbasis tumpukan. Secara umum, saya akan mengatakan bahwa sebagian besar masalah desain, bukan masalah implementasi.
sumber
Berapa lama waktu yang dibutuhkan sebagai klien? sangat sedikit, begitu Anda terbiasa. ketika sebuah wadah mengelola referensi seumur hidup, itu sangat mudah. imo, ini jauh lebih sederhana daripada penghitungan referensi manual, dan itu praktis transparan jika Anda menganggap wadah yang Anda gunakan sebagai dokumentasi yang dengan mudahnya membuat Anda tidak melakukan transfer kepemilikan yang tidak sah dalam sistem typesafe yang dirancang dengan baik.
sebagian besar waktu yang saya habiskan (sebagai klien) dihabiskan berisi jenis-jenis dari apis lain, sehingga mereka berfungsi dengan baik dalam konteks program Anda. Contoh: ini adalah wadah ThirdPartyFont saya, dan mendukung fitur ini, dan kehancuran alat cara ini, dan referensi menghitung cara ini, dan menyalin cara ini, dan ... . Banyak dari konstruksi itu harus ada, dan seringkali merupakan tempat yang logis untuk menempatkannya. apakah Anda ingin memasukkan itu sebagai waktu atau tidak tergantung pada definisi Anda (implementasi perlu ada ketika berinteraksi dengan apis ini, toh, kan?).
setelah itu, Anda perlu mempertimbangkan dan mempertimbangkan kepemilikan. dalam sistem tingkat yang lebih rendah, itu bagus dan perlu, tetapi bisa membutuhkan waktu dan perancah untuk menerapkan bagaimana Anda harus memindahkan barang-barang. saya tidak melihatnya sebagai rasa sakit karena ini adalah persyaratan sistem tingkat yang lebih rendah. kepemilikan, kontrol, dan tanggung jawab sudah jelas.
jadi kita bisa mengubahnya menjadi apis berbasis c yang menggunakan jenis buram: wadah kami memungkinkan kami untuk abstrak semua detail implementasi kecil mengelola masa hidup dan menyalin jenis-jenis buram, yang pada akhirnya membuat pengelolaan sumber daya sangat sangat sederhana dan menghemat waktu, cacat, dan mengurangi implementasi.
itu benar-benar sangat sederhana untuk menggunakan ini - masalahnya (berasal dari GC) adalah bahwa Anda sekarang harus mempertimbangkan masa hidup sumber daya Anda. jika Anda salah, mungkin perlu banyak waktu untuk menyelesaikannya. belajar dan mengintegrasikan manajemen seumur hidup yang eksplisit dapat dipahami rumit jika dibandingkan (bukan untuk semua orang) - itulah rintangan sesungguhnya. sekali Anda nyaman mengendalikan masa hidup dan menggunakan solusi yang baik, maka sangat mudah untuk mengelola masa pakai sumber daya. itu bukan bagian penting dari hari saya (kecuali bug yang sulit telah merangkak masuk).
jika Anda tidak menggunakan wadah (auto / shared pointer), maka Anda hanya memohon rasa sakit.
saya sudah mengimplementasikan perpustakaan saya sendiri. saya perlu waktu untuk mengimplementasikan hal-hal itu, tetapi kebanyakan orang menggunakan kembali (yang biasanya merupakan ide yang baik).
sumber
Maksud Anda seperti secara manual harus membebaskan memori, menutup file, hal-hal semacam ini? Jika demikian, saya akan mengatakan minimum dan biasanya kurang dari sebagian besar bahasa lain yang saya gunakan, terutama jika kita menggeneralisasikannya tidak hanya untuk "manajemen memori" tetapi "manajemen sumber daya." Dalam hal itu, saya benar-benar berpikir C ++ memerlukan lebih sedikit manajemen sumber daya manual daripada, katakanlah Java atau C #.
Ini terutama disebabkan oleh destruktor yang secara otomatis menghancurkan sumber daya (memori atau lainnya). Biasanya satu-satunya waktu saya harus membebaskan / menghancurkan sumber daya secara manual dalam C ++ adalah jika saya menerapkan struktur data level-vlow (sesuatu yang kebanyakan orang tidak perlu lakukan) atau menggunakan C API di mana saya hanya menghabiskan sedikit waktu membungkus sumber daya C yang perlu secara manual dibebaskan / dihancurkan / ditutup menjadi pembungkus C ++ yang sesuai dengan RAII.
Tentu saja jika pengguna meminta untuk menutup gambar dalam perangkat lunak pengedit gambar, saya harus menghapus gambar dari koleksi atau sesuatu. Tapi mudah-mudahan itu tidak dianggap sebagai manajemen "memori" atau "sumber daya" yang penting dalam konteks ini, karena itu cukup banyak diperlukan dalam bahasa apa pun jika Anda ingin membebaskan memori yang terkait dengan gambar itu pada waktu itu. Tapi sekali lagi yang harus Anda lakukan adalah menghapus gambar dari koleksi dan penghancur gambar mengurus sisanya.
Sementara itu jika saya bandingkan dengan, katakanlah, Java atau C #, Anda sering menemukan orang harus menutup file secara manual di sana, mencabut soket secara manual, mengatur referensi objek ke nol untuk memungkinkan mereka menjadi sampah yang dikumpulkan, dll. Ada jauh lebih banyak memori manual dan manajemen sumber daya dalam bahasa-bahasa itu jika Anda bertanya kepada saya. Dalam C ++ Anda bahkan sering tidak perlu
unlock
mutex secara manual, karena loker mutex akan melakukannya untuk Anda secara otomatis ketika mutex keluar dari ruang lingkup. Misalnya, Anda tidak perlu melakukan hal-hal seperti ini di C ++:Tidak perlu melakukan hal-hal seperti menutup file secara manual di C ++. Mereka akhirnya menutup diri secara otomatis begitu mereka keluar dari ruang lingkup apakah mereka keluar dari ruang lingkup sebagai akibat atau jalur eksekusi normal atau luar biasa. Hal serupa untuk sumber daya terkait memori seperti
std::vector
. Kode seperti difile.Close()
atas akan sering disukai karena, terutama dalam konteksfinally
blok, yang menunjukkan sumber daya lokal perlu dibebaskan secara manual ketika seluruh pola pikir sekitar C ++ adalah untuk mengotomatisasi itu.Dalam hal manajemen memori manual, saya akan mengatakan C membutuhkan maksimum, Java / C # jumlah sedang, dan C ++ minimum di antaranya. Ada banyak alasan untuk sedikit malu menggunakan C ++ karena ini adalah bahasa yang sangat sulit untuk dikuasai, tetapi manajemen memori tidak boleh menjadi salah satunya. Sebaliknya saya benar-benar berpikir itu adalah salah satu bahasa yang paling mudah di luar sana dalam aspek yang satu ini.
Tentu saja C ++ tidak membiarkan Anda mulai mengalokasikan memori secara manual dan memohon
operator delete/delete[]
untuk membebaskan memori secara manual. Ini juga memungkinkan Anda menggunakan fungsi C sepertimalloc
danfree
. Tapi itu semacam praktik pengkodean gaya kuno yang menurut saya sudah usang jauh sebelum orang-orang memberi penghargaan, karena Stroustrup menganjurkan RAII sebelum dia bahkan menciptakan istilah itu sejak awal. Jadi saya bahkan tidak berpikir itu adil untuk mengatakan "C ++ modern" mengotomatisasi manajemen sumber daya, karena itu seharusnya menjadi tujuan selama ini. Anda tidak bisa mendapatkan keselamatan pengecualian jika tidak. Hanya saja, banyak pengembang yang salah kaprah selama awal 90-an mencoba menggunakan C ++ seperti halnya C dengan objek, seringkali mengabaikan penanganan pengecualian, dan tidak pernah seharusnya digunakan seperti itu. Jika Anda menggunakan C ++ dengan cara yang praktis selalu dimaksudkan untuk digunakan, maka manajemen memori benar-benar otomatis dan umumnya bukan sesuatu yang harus Anda tangani secara manual (atau harus berurusan dengan) sama sekali.sumber
Tergantung pada petunjuk teknis senior dalam tim. Di beberapa perusahaan (termasuk tambang), tidak ada konsep yang disebut smart poiner. Itu dianggap mewah. Jadi, orang cukup menghapus semua tempat dan ada drive untuk memperbaiki kebocoran memori setiap 2 bulan. Gelombang baru pernyataan penghapusan tiba di mana-mana. Jadi, tergantung pada perusahaan dan jenis orang yang bekerja di sana.
sumber
auto_ptr
dan berteman?