Merancang sistem baru dari awal. Saya akan menggunakan STL untuk menyimpan daftar dan peta objek berumur panjang tertentu.
Pertanyaan: Haruskah saya memastikan objek saya memiliki konstruktor salinan dan menyimpan salinan objek dalam wadah STL saya, atau apakah secara umum lebih baik untuk mengelola kehidupan & ruang lingkup sendiri dan hanya menyimpan pointer ke objek-objek tersebut dalam wadah STL saya?
Saya menyadari ini agak pendek pada detail, tetapi saya mencari jawaban "teoretis" yang lebih baik jika ada, karena saya tahu kedua solusi ini mungkin.
Dua kerugian yang sangat jelas untuk bermain dengan pointer: 1) Saya harus mengatur sendiri alokasi / deallokasi objek-objek ini dalam lingkup di luar STL. 2) Saya tidak bisa membuat objek temp pada stack dan menambahkannya ke wadah saya.
Apakah ada hal lain yang saya lewatkan?
Jawaban:
Karena orang-orang berbicara tentang efisiensi penggunaan pointer.
Jika Anda mempertimbangkan untuk menggunakan std :: vector dan jika pembaruan sedikit dan Anda sering beralih ke koleksi Anda dan itu adalah jenis "salinan" objek penyimpanan non-polimorfik akan lebih efisien karena Anda akan mendapatkan lokalitas referensi yang lebih baik.
Otoh, jika pembaruan adalah pointer penyimpanan umum akan menghemat biaya salinan / relokasi.
sumber
Ini sangat tergantung pada situasi Anda.
Jika objek Anda kecil, dan melakukan salinan objek itu ringan, maka menyimpan data di dalam wadah stl mudah dan mudah dikelola menurut saya karena Anda tidak perlu khawatir tentang manajemen seumur hidup.
Jika objek Anda besar, dan memiliki konstruktor default tidak masuk akal, atau salinan objek mahal, maka menyimpan dengan pointer mungkin merupakan cara yang harus dilakukan.
Jika Anda memutuskan untuk menggunakan pointer ke objek, lihat di Perpustakaan Boost Pointer Container . Pustaka pendorong ini membungkus semua wadah STL untuk digunakan dengan objek yang dialokasikan secara dinamis.
Setiap wadah penunjuk (misalnya ptr_vector) mengambil kepemilikan suatu objek saat ditambahkan ke wadah, dan mengelola masa pakai objek tersebut untuk Anda. Anda juga mengakses semua elemen dalam wadah ptr_ dengan referensi. Ini memungkinkan Anda melakukan hal-hal seperti
Kelas-kelas ini membungkus wadah STL dan bekerja dengan semua algoritma STL, yang sangat berguna.
Ada juga fasilitas untuk mentransfer kepemilikan pointer di wadah ke pemanggil (melalui fungsi rilis di sebagian besar kontainer).
sumber
Jika Anda menyimpan objek polimorfik, Anda selalu perlu menggunakan koleksi pointer kelas dasar.
Itu adalah jika Anda berencana untuk menyimpan berbagai jenis turunan dalam koleksi Anda, Anda harus menyimpan pointer atau dimakan oleh deamon pengiris.
sumber
Maaf untuk melompat 3 tahun setelah acara, tetapi catatan peringatan di sini ...
Pada proyek besar terakhir saya, struktur data pusat saya adalah satu set objek yang cukup mudah. Sekitar satu tahun dalam proyek ini, ketika persyaratan berkembang, saya menyadari bahwa objek tersebut sebenarnya perlu polimorfik. Butuh beberapa minggu operasi otak yang sulit dan buruk untuk memperbaiki struktur data menjadi satu set pointer kelas dasar, dan untuk menangani semua kerusakan jaminan dalam penyimpanan objek, casting, dan sebagainya. Butuh beberapa bulan untuk meyakinkan diri saya bahwa kode baru itu berfungsi. Kebetulan, ini membuat saya berpikir keras tentang bagaimana model objek C ++ yang dirancang dengan baik.
Pada proyek besar saya saat ini, struktur data pusat saya adalah satu set objek yang cukup mudah. Sekitar setahun ke proyek (yang kebetulan hari ini), saya menyadari bahwa objek tersebut sebenarnya harus polimorfik. Kembali ke internet, temukan utas ini, dan temukan tautan Nick ke pustaka wadah penunjuk Boost. Inilah yang saya harus tulis terakhir kali untuk memperbaiki semuanya, jadi saya akan mencobanya kali ini.
Moral, bagi saya, bagaimanapun: jika spec Anda tidak 100% dilemparkan ke batu, pergi untuk pointer, dan Anda mungkin berpotensi menghemat banyak pekerjaan nanti.
sumber
Mengapa tidak mendapatkan yang terbaik dari kedua dunia: lakukan wadah petunjuk pintar (seperti
boost::shared_ptr
ataustd::shared_ptr
). Anda tidak harus mengelola memori, dan Anda tidak harus berurusan dengan operasi penyalinan besar.sumber
Umumnya menyimpan objek secara langsung dalam wadah STL adalah yang terbaik karena paling sederhana, paling efisien, dan paling mudah untuk menggunakan objek.
Jika objek Anda sendiri memiliki sintaks yang tidak dapat disalin atau merupakan tipe basis abstrak, Anda harus menyimpan pointer (yang paling mudah adalah menggunakan shared_ptr)
sumber
Anda tampaknya memiliki pemahaman yang baik tentang perbedaan itu. Jika objek kecil dan mudah disalin, maka simpanlah.
Jika tidak, saya akan berpikir tentang menyimpan pointer pintar (bukan auto_ptr, ref pointer pintar menghitung) untuk yang Anda alokasikan pada heap. Jelas, jika Anda memilih pointer pintar, maka Anda tidak dapat menyimpan objek temp stack yang dialokasikan (seperti yang Anda katakan).
@ Torbjörn membuat poin bagus tentang mengiris.
sumber
one
keanother
akan merilis referensi darione
dan mengubahone
.Menggunakan pointer akan lebih efisien karena wadah hanya akan menyalin pointer daripada benda penuh.
Ada beberapa informasi berguna di sini tentang kontainer STL dan smart pointer:
Mengapa salah menggunakan std :: auto_ptr <> dengan kontainer standar?
sumber
Jika objek akan dirujuk ke tempat lain dalam kode, simpan dalam vektor boost :: shared_ptr. Ini memastikan bahwa pointer ke objek akan tetap valid jika Anda mengubah ukuran vektor.
Yaitu:
Jika tidak ada orang lain yang menyimpan pointer ke objek, atau daftar tidak tumbuh dan menyusut, simpan saja sebagai objek tua-polos:
sumber
Pertanyaan ini telah mengganggu saya untuk sementara waktu.
Saya cenderung untuk menyimpan pointer, tetapi saya memiliki beberapa persyaratan tambahan (pembungkus SWIG lua) yang mungkin tidak berlaku untuk Anda.
Poin paling penting dalam postingan ini adalah untuk mengujinya sendiri , menggunakan objek Anda
Saya melakukan ini hari ini untuk menguji kecepatan memanggil fungsi anggota pada koleksi 10 juta objek, 500 kali.
Fungsi memperbarui x dan y berdasarkan xdir dan ydir (semua variabel anggota float).
Saya menggunakan std :: list untuk menampung kedua jenis objek, dan saya menemukan bahwa menyimpan objek dalam daftar sedikit lebih cepat daripada menggunakan pointer. Di sisi lain, kinerjanya sangat dekat, sehingga tergantung pada bagaimana mereka akan digunakan dalam aplikasi Anda.
Untuk referensi, dengan -O3 pada perangkat keras saya pointer butuh 41 detik untuk menyelesaikan dan objek mentah butuh 30 detik untuk menyelesaikan.
sumber