menggunakan pointer non-pintar di C++ modern

Versi Singkat:
Apakah ada alasan yang dapat diterima untuk menggunakan pointer non-pintar di C++ modern?

Versi Panjang:
kami memiliki produk besar yang berisi banyak kode C++ lama dan sekarang kami mencoba memfaktorkannya kembali ke era C++ modern. Seiring dengan semua kode kuno, ada sejumlah besar petunjuk yang beredar (kebanyakan dengan anotasi SAL untuk memberikan rasa aman) dan saya bertanya-tanya apakah kita harus mengubah semuanya menjadi petunjuk cerdas atau mungkin membiarkan beberapa di antaranya apa adanya. ?
Saat mencoba mengonversi beberapa kode ini, saya mendapatkan kode yang bisa diperdebatkan karena penggunaan smart pointer.

Jadi pertanyaannya adalah: apakah ada yang namanya penggunaan smart pointer secara berlebihan?
Atau dengan kata lain: apakah ada skenario yang dapat diterima untuk non-smart pointer saat ini?


person MBZ    schedule 17.10.2013    source sumber
comment
Jika mereka tidak memiliki apa pun, tidak ada gunanya.   -  person chris    schedule 17.10.2013
comment
Masalahnya adalah mereka mungkin seharusnya tidak menjadi pointer sama sekali (pointer mentah tidak memiliki banyak tempat di c++ modern seperti yang Anda katakan) tetapi juga jika tidak rusak jangan perbaiki   -  person aaronman    schedule 17.10.2013
comment
pointer mentah baik-baik saja di c++ modern jika mereka tidak memiliki sumber daya apa pun. Itu berarti Anda tidak perlu mengubah semua pointer mentah menjadi pointer cerdas.   -  person StereoMatching    schedule 17.10.2013


Jawaban (5)


Pointer pintar (unique_ptr dan shared_ptr) harus menjadi pointer MEMILIKI (yaitu, bertanggung jawab atas penghancuran objek). Inti dari penggunaannya adalah bahwa objek apa pun yang dibuat oleh new harus dimasukkan ke dalam unique_ptr ASAP, untuk mencegah kebocoran memori. Setelah itu, unique_ptr seharusnya dipindahkan:

  • baik menjadi shared_ptr jika kepemilikan harus dibagi,
  • atau menjadi unique_ptr jika kepemilikan ditentukan oleh cakupan (sebuah blok, atau masa hidup suatu objek).

releases seharusnya jarang terjadi. Jika kode Anda meneruskan petunjuk yang tidak dimiliki, ini seharusnya:

  • petunjuk mentah jika mungkin null, (diperoleh oleh get)
  • referensi jika mungkin bukan null, (diperoleh oleh get)
  • unique_ptrs berdasarkan nilai jika tujuan panggilan adalah mentransfer kepemilikan. (dalam hal ini Anda harus memindahkannya)

Metode pabrik harus mengembalikan unique_ptrs berdasarkan nilai. (karena kemudian, jika Anda tidak menetapkan nilai pengembalian metode pabrik, objek akan segera dibatalkan alokasinya)

Dan lihat jawaban Ali mengenai tautan ke beberapa poin filosofis dalam menangani kode warisan. (Yang saya setujui sepenuhnya)

person Laurent LA RIZZA    schedule 17.10.2013

Versi Singkat:
Apakah ada alasan yang dapat diterima untuk menggunakan pointer non-pintar di C++ modern?

Jawaban singkat:

Tentu saja, jika mereka hanya berfungsi untuk observasi, artinya mereka bukan pemilik pointee tersebut. Namun, cobalah untuk menggunakan referensi alih-alih petunjuk bahkan dalam kasus ini; gunakan pointer hanya jika Anda benar-benar perlu menjadikannya opsional (inisialisasi dengan null_ptr lalu tetapkan kembali nanti, misalnya).

Versi Panjang:
kami memiliki produk besar yang berisi banyak kode C++ lama dan sekarang kami mencoba memfaktorkannya kembali ke era C++ modern. [...]

Jawaban panjang:

Saat saya membaca baris-baris ini, jawaban ini muncul di benak saya:

Saya berharap saya dapat memberi suara positif pada jawaban ini lebih dari sekali. Saya akan mengutip: "[...] untuk setiap faktor ulang yang telah kita buat, kita dapat membenarkan 'perubahan spesifik ini akan membuat tugas sebenarnya yang kita lakukan sekarang menjadi lebih mudah'. Daripada 'ini sekarang lebih bersih untuk pekerjaan di masa depan '."

Singkat cerita, jangan lakukan refactoring besar-besaran kecuali Anda benar-benar membutuhkannya.

Jadi pertanyaannya adalah: apakah ada yang namanya penggunaan smart pointer secara berlebihan?

Menurut pendapat saya, std::shared_ptr digunakan secara berlebihan. Sangat nyaman digunakan, dan memberi Anda ilusi bahwa Anda tidak perlu memikirkan masalah kepemilikan. Tapi itu bukanlah gambaran keseluruhan. Saya sepenuhnya setuju dengan Sean Parent: "penunjuk bersama sama baiknya dengan variabel global." Petunjuk bersama juga dapat menimbulkan masalah kepemilikan yang sangat sulit, dll.

Di sisi lain, jika Anda perlu mengalokasikan sesuatu di heap, gunakan unique_ptr. Anda tidak boleh menggunakannya secara berlebihan, jika Anda benar-benar memerlukan alokasi heap. Menurut pengalaman saya, menggunakan unique_ptr juga menghasilkan kode yang lebih bersih dan mudah dipahami, karena masalah kepemilikan menjadi cukup jelas.

Pembicaraan menarik dari Sean Parent tentang cara menghindari/mengurangi penggunaan pointer adalah:

Semoga ini membantu.

person Ali    schedule 17.10.2013

Ya, pointer mentah masih memiliki kegunaan sebagai "referensi opsional". Yaitu. a T* mirip dengan T&. Tidak ada yang menyiratkan kepemilikan, namun T* bisa menjadi nullptr.

person MSalters    schedule 17.10.2013
comment
Tapi tentunya ada alternatif yang lebih aman daripada petunjuk mentah untuk ini? Saya sedang memikirkan tipe optional boost (sekarang juga std::experimental) karena sudah jelas apa yang terjadi, tetapi bahkan hanya smart pointer saja dapat digunakan dengan cara ini. - person JimmidyJoo; 02.05.2016
comment
@JimmidyJoo: Ya, saya melakukan pengamatan yang sama persis kemarin - person MSalters; 02.05.2016

Lihat pembicaraannya di sini: http://channel9.msdn.com/Events/GoingNative/2013 (terutama pembicaraan Stroustrup).

Jawaban singkatnya adalah tidak, dengan asumsi "C++ modern" adalah >= c++11

Jawaban panjangnya adalah hal ini tidak selalu terjadi dan mencoba merestrukturisasi proyek besar hampir selalu sulit. Cara kita berpikir mengenai masalah dibatasi oleh alat yang kita miliki untuk menyelesaikannya. Ada banyak kasus ketika melakukan pemfaktoran ulang seperti itu ketika menggunakan pointer lebih masuk akal daripada mencoba mengekspresikan ulang logika dasar agar ramah kelas dan penunjuk cerdas. Saya pikir ini bukan kasus di mana smart pointer digunakan secara berlebihan dan lebih merupakan kasus ketika kelas kurang digunakan. YMMV ;-)

person Dweeberly    schedule 17.10.2013
comment
um apa arti C++ modern ›= c++11 - person aaronman; 17.10.2013
comment
@aaronman Dengan asumsi bahwa dengan 'C++ modern' OP berarti C++11 atau lebih baru - person Jonathan Potter; 17.10.2013
comment
Ya, hampir tidak ada alasan untuk menulis kode buruk di C++03. - person R. Martinho Fernandes; 17.10.2013

Tentu saja ada kasus penggunaan untuk pointer mentah di C++ modern:

  • antarmuka yang harus dapat dikompilasi sebagai C murni (walaupun implementasinya sendiri dapat menggunakan fitur-fitur C++ tersebut, yang bukan juga fitur-fitur C, seperti kelas, atau smart-pointer)
  • kode yang levelnya sangat rendah, levelnya sangat rendah, bahkan smart-pointer yang paling sederhana pun terbukti terlalu berat

Tentu saja itu adalah kasus yang agak jarang terjadi dan sejauh ini sebagian besar kasus penggunaan pointer smart pointer seharusnya baik-baik saja untuk kode baru, TETAPI:

Jika kode yang ada berfungsi dengan baik dengan pointer mentah, mengapa menginvestasikan waktu untuk menulis ulang dan berisiko menambahkan bug saat mengonversinya menjadi smart-pointer menggunakan versi?

Jangan memfaktorkan ulang kode, itu berfungsi dengan baik, hanya karena kode baru lebih mengikuti standar pemrograman modern. Standar pemrograman ini tidak ada untuk kepentingan mereka sendiri, tetapi untuk membuat bekerja dengan beberapa kode lebih mudah, jadi jangan lakukan refactoring, yang akan menghabiskan lebih banyak waktu daripada menghemat waktu Anda di masa depan.

Artinya: Jika Anda memerlukan lebih banyak waktu untuk memeriksa, pointer mana yang dapat dengan aman diubah menjadi smart-pointer dan mana yang tidak bisa dan untuk memburu bug, yang mungkin disebabkan oleh pemfaktoran ulang Anda, maka Anda dapat menghemat pada pekerjaan pemeliharaan di masa mendatang karena pemfaktoran ulang, jangan lakukan pemfaktoran ulang dan biarkan tetap apa adanya.

Jika pemfaktoran ulang akan menghemat lebih banyak waktu daripada biaya untuk beberapa bagian basis kode saja, maka pertimbangkan untuk hanya memfaktorkan ulang bagian basis kode tersebut.

person Kaiserludi    schedule 17.10.2013