Saya membaca di beberapa artikel bahwa pointer mentah hampir tidak boleh digunakan. Alih-alih, mereka harus selalu dibungkus dengan pointer pintar, apakah itu scoped atau shared pointer.
Namun, saya perhatikan bahwa kerangka kerja seperti Qt, wxWidgets dan perpustakaan seperti Boost tidak pernah kembali atau mengharapkan pointer pintar, seolah-olah mereka tidak menggunakannya sama sekali. Sebaliknya, mereka kembali atau mengharapkan pointer mentah. Apakah ada alasan untuk itu? Haruskah saya menjauh dari smart pointer ketika saya menulis API publik, dan mengapa?
Hanya ingin tahu mengapa pointer cerdas direkomendasikan ketika banyak proyek besar tampaknya menghindarinya.
c++
api
pointers
smart-pointers
laurent
sumber
sumber
unique_ptr
? Tidak ada sama sekali. Apakah Qt / WxWidget ditargetkan pada sistem embedded atau real time? Tidak, itu dimaksudkan untuk Windows / Mac / Unix di desktop paling banyak. Pointer pintar adalah untuk programmer yang ingin memperbaikinya.Jawaban:
Terlepas dari kenyataan bahwa banyak perpustakaan ditulis sebelum munculnya smart pointer standar, alasan terbesar mungkin adalah kurangnya standar C ++ Application Binary Interface (ABI).
Jika Anda menulis pustaka header saja, Anda bisa membagikan smart pointer dan kontainer standar ke isi hati Anda. Sumbernya tersedia untuk pustaka Anda pada waktu kompilasi, jadi Anda mengandalkan stabilitas antarmuka mereka sendiri, bukan pada implementasinya.
Tetapi karena kurangnya ABI standar, Anda umumnya tidak dapat melewatkan objek-objek ini dengan aman melintasi batas-batas modul. GCC
shared_ptr
mungkin berbeda dari MSVCshared_ptr
, yang juga bisa berbeda dari Intelshared_ptr
. Bahkan dengan kompiler yang sama , kelas-kelas ini tidak dijamin biner kompatibel antar versi.Intinya adalah bahwa jika Anda ingin mendistribusikan versi prebuilt perpustakaan Anda, Anda memerlukan ABI standar untuk dapat diandalkan. C tidak memilikinya, tetapi vendor kompiler sangat bagus dalam hal interoperabilitas antara pustaka C untuk platform tertentu — ada standar de facto.
Situasinya tidak sebaik C ++. Kompiler individual dapat menangani interoperasi antara biner mereka sendiri, sehingga Anda memiliki opsi untuk mendistribusikan versi untuk setiap kompiler yang didukung, seringkali GCC dan MSVC. Tetapi mengingat hal ini, sebagian besar perpustakaan hanya mengekspor antarmuka C — dan itu berarti pointer mentah.
Namun, kode non-perpustakaan umumnya lebih suka pointer pintar daripada mentah.
sumber
Mungkin ada banyak alasan. Untuk membuat daftar beberapa di antaranya:
Sunting : Menggunakan smart pointer adalah pilihan sepenuhnya pengembang. Itu tergantung pada berbagai faktor.
Dalam sistem kritis kinerja, Anda mungkin tidak ingin menggunakan smart pointer yang menghasilkan overhead
Proyek yang membutuhkan kompatibilitas ke belakang, Anda mungkin tidak ingin menggunakan smart pointer yang memiliki fitur khusus C ++ 11
Sunting2 Ada serangkaian beberapa downvotes dalam rentang 24 jam karena bagian di bawah ini. Saya gagal memahami mengapa jawabannya diturunkan meskipun di bawah ini hanya saran tambahan dan bukan jawaban.
Namun, C ++ selalu memfasilitasi Anda untuk membuka opsi. :) mis
Dan dalam kode Anda menggunakannya sebagai:
Bagi mereka yang mengatakan bahwa smart pointer dan raw pointer berbeda, saya setuju dengan itu. Kode di atas hanyalah sebuah ide di mana seseorang dapat menulis kode yang dapat dipertukarkan hanya dengan a
#define
, ini bukan paksaan ;Sebagai contoh,
T*
harus dihapus secara eksplisit tetapi pointer pintar tidak. Kita dapat memiliki templatedDestroy()
untuk mengatasinya.dan gunakan sebagai:
Dengan cara yang sama, untuk pointer mentah kita dapat menyalinnya secara langsung dan untuk smart pointer kita dapat menggunakan operasi khusus.
Di mana
Assign()
adalah sebagai:sumber
std::auto_ptr
yang telah menjadi bagian dari standar untuk waktu yang lama (dan perhatikan, saya memang sukastd::auto_ptr
sebagai tipe pengembalian untuk fungsi yang membuat objek, bahkan jika itu adalah hampir tidak berguna di tempat lain). Dalam C ++ 11std::unique_ptr
tidak memiliki biaya tambahan atas pointer biasa.unique_ptr
dan menghilangnyaauto_ptr
, penargetan kode C ++ 03 harus menggunakan yang lebih baru, sementara penargetan kode C ++ 11 dapat menggunakan yang sebelumnya. Pointer pintar tidakshared_ptr
, ada banyak standar dan tidak ada standar, termasuk proposal dengan standar yang ditolak sebagaimanaged_ptr
unique_ptr
biaya runtime, tetapiunique_ptr
sejauh ini adalah salah satu yang paling umum digunakan. Sampel kode yang Anda berikan juga menyesatkan, karenaunique_ptr
danT*
sepenuhnya merupakan konsep yang berbeda. Fakta bahwa Anda merujuk keduanya sama-samatype
memberikan kesan bahwa mereka dapat saling bertukar satu sama lain.Ada dua masalah dengan smart pointer (pra C ++ 11):
The standar pointer cerdas, dalam hal ini adalah bebas biaya, adalah
unique_ptr
. Sayangnya itu membutuhkan semantik bergerak C ++ 11, yang hanya muncul baru-baru ini. Semua pointer pintar lainnya memiliki biaya (shared_ptr
,intrusive_ptr
) atau memiliki semantik yang kurang ideal (auto_ptr
).Dengan C ++ 11 di tikungan, membawa
std::unique_ptr
, orang akan tergoda untuk berpikir bahwa itu akhirnya berakhir ... Saya tidak begitu optimis.Hanya beberapa kompiler utama yang mengimplementasikan sebagian besar C ++ 11, dan hanya dalam versi terbaru mereka. Kita dapat mengharapkan perpustakaan besar seperti QT dan Boost untuk bersedia mempertahankan kompatibilitas dengan C ++ 03 untuk sementara waktu, yang agak menghalangi adopsi luas dari smart pointer yang baru dan mengkilap.
sumber
Anda tidak boleh tinggal jauh dari smart pointer, mereka menggunakannya terutama dalam aplikasi di mana Anda harus melewati objek.
Perpustakaan cenderung hanya mengembalikan nilai atau mengisi objek. Mereka biasanya tidak memiliki objek yang perlu digunakan di banyak tempat, jadi tidak perlu bagi mereka untuk menggunakan smart pointer (setidaknya tidak dalam antarmuka mereka, mereka dapat menggunakannya secara internal).
Saya dapat mengambil contoh perpustakaan yang telah kami kerjakan, di mana setelah beberapa bulan pengembangan saya menyadari bahwa kami hanya menggunakan pointer dan smart pointer di beberapa kelas (3-5% dari semua kelas).
Melewati variabel dengan referensi sudah cukup di sebagian besar tempat, kami menggunakan pointer pintar setiap kali kami memiliki objek yang bisa nol, dan pointer mentah ketika perpustakaan yang kami gunakan memaksa kami untuk.
Sunting (Saya tidak dapat berkomentar karena reputasi saya): meneruskan variabel dengan referensi sangat fleksibel: jika Anda ingin objek dibaca hanya Anda dapat menggunakan referensi const (Anda masih dapat melakukan beberapa gips jahat untuk dapat menulis objek) ) tetapi Anda mendapatkan perlindungan maksimal (sama dengan smart pointer). Tapi saya setuju bahwa itu jauh lebih baik untuk hanya mengembalikan objek.
sumber
Qt tanpa sengaja menemukan kembali banyak bagian dari pustaka Standar dalam upaya untuk menjadi Java. Saya percaya bahwa itu memang memiliki pointer pintar sendiri sekarang, tetapi secara umum, itu bukan puncak dari desain. wxWidgets, sejauh yang saya ketahui, dirancang jauh sebelum pointer pintar yang dapat digunakan ditulis.
Adapun Boost, saya sepenuhnya berharap mereka menggunakan pointer pintar di mana pun sesuai. Anda mungkin harus lebih spesifik.
Selain itu, jangan lupa bahwa pointer cerdas ada untuk menegakkan kepemilikan. Jika API tidak memiliki semantik kepemilikan, lalu mengapa menggunakan smart pointer?
sumber
QString
, wxWidgets milikiwxString
, MFC memiliki nama yang mengerikanCString
. Bukankah UTF-8std::string
cukup baik untuk 99% tugas GUI?Pertanyaan bagus. Saya tidak tahu artikel spesifik yang Anda referensikan, tetapi saya telah membaca hal-hal serupa dari waktu ke waktu. Kecurigaan saya adalah bahwa para penulis artikel semacam itu cenderung memiliki bias terhadap pemrograman gaya C ++. Jika penulis memprogram dalam C ++ hanya ketika ia harus, kemudian kembali ke Jawa atau secepatnya, maka ia tidak benar-benar berbagi pola pikir C ++.
Seseorang mencurigai bahwa beberapa atau sebagian besar penulis yang sama lebih suka pengelola memori pengumpul sampah. Saya tidak, tetapi saya berpikir berbeda dari mereka.
Pointer pintar bagus, tetapi mereka harus menjaga jumlah referensi. Menyimpan jumlah referensi dikenakan biaya - sering biaya sederhana, tetapi biaya tetap - pada saat runtime. Tidak ada yang salah dengan menghemat biaya ini dengan menggunakan pointer kosong, terutama jika pointer dikelola oleh destruktor.
Salah satu hal terbaik tentang C ++ adalah dukungannya untuk pemrograman embedded-system. Penggunaan bare pointer adalah bagian dari itu.
Pembaruan: Seorang komentator telah mengamati dengan benar bahwa C ++ yang baru
unique_ptr
(tersedia sejak TR1) tidak menghitung referensi. Komentator juga memiliki definisi "penunjuk pintar" yang berbeda dari yang ada dalam pikiran saya. Dia mungkin benar tentang definisi itu.Pembaruan lebih lanjut: Utas komentar di bawah ini menyinari. Semua itu dianjurkan dibaca.
sumber
shared_ptr
simpan penghitungan referensi. Ada banyak jenis penunjuk pintar lainnya yang tidak memiliki jumlah referensi sama sekali. Akhirnya, perpustakaan yang disebutkan ditargetkan pada platform yang memiliki banyak sumber daya cadangan. Bukan karena saya yang downvoter, tapi yang saya katakan adalah bahwa posting Anda penuh dengan kesalahan.shared_ptr
tidak memiliki overhead. Ini hanya memiliki overhead jika Anda tidak memerlukan semantik kepemilikan bersama aman, yang disediakannya.Ada juga tipe smart pointer lainnya. Anda mungkin ingin penunjuk pintar khusus untuk sesuatu seperti replikasi jaringan (yang mendeteksi apakah itu diakses dan mengirimkan modifikasi apa pun ke server atau semacamnya), menyimpan sejarah perubahan, menandai fakta bahwa itu diakses sehingga dapat diselidiki ketika Anda menyimpan data ke disk dan sebagainya. Tidak yakin apakah melakukan hal itu di pointer adalah solusi terbaik, tetapi menggunakan smart pointer yang ada di perpustakaan dapat mengakibatkan orang terkunci di dalamnya dan kehilangan fleksibilitas.
Orang dapat memiliki semua jenis persyaratan dan solusi manajemen memori yang berbeda di luar smart pointer. Saya mungkin ingin mengelola memori sendiri, saya bisa mengalokasikan ruang untuk hal-hal dalam kumpulan memori sehingga dialokasikan terlebih dahulu dan bukan pada saat runtime (berguna untuk game). Saya mungkin menggunakan implementasi pengumpulan sampah C ++ (C ++ 11 memungkinkan hal ini terjadi walaupun belum ada). Atau mungkin saya hanya tidak melakukan sesuatu yang cukup lanjut untuk khawatir tentang mengganggu mereka, saya bisa tahu bahwa saya tidak akan lupa untuk objek yang tidak diinisialisasi dan sebagainya. Mungkin saya hanya percaya diri dengan kemampuan saya mengelola memori tanpa penunjuk pointer.
Integrasi dengan C juga merupakan masalah lain.
Masalah lainnya adalah smart pointer adalah bagian dari STL. C ++ dirancang agar dapat digunakan tanpa STL.
sumber
Ini juga tergantung pada domain tempat Anda bekerja. Saya menulis mesin gim untuk mencari nafkah, kami menghindari dorongan seperti wabah, di gim biaya tambahan tidak dapat diterima. Di mesin inti kami, kami akhirnya menulis versi kami sendiri stl (Sama seperti ea stl).
Jika saya menulis formulir aplikasi, saya mungkin mempertimbangkan untuk menggunakan smart pointer; tetapi begitu manajemen memori adalah sifat kedua, tidak memiliki kendali granular atas memori menjadi sangat mengganggu.
sumber