Jawaban:
Mudah ketika Anda memiliki properti yang dapat Anda tetapkan setiap penunjuk pintar. Ada tiga sifat penting.
Yang pertama berarti bahwa pointer pintar tidak dapat menghapus objek, karena itu bukan miliknya. Yang kedua berarti bahwa hanya satu pointer cerdas yang dapat menunjuk ke objek yang sama pada saat yang sama. Jika smart pointer harus dikembalikan dari fungsi, kepemilikannya ditransfer ke smart pointer yang dikembalikan, misalnya.
Yang ketiga berarti bahwa beberapa pointer cerdas dapat menunjuk ke objek yang sama pada saat yang sama. Ini berlaku untuk pointer mentah juga, tetapi pointer mentah tidak memiliki fitur penting: Mereka tidak menentukan apakah mereka memiliki atau tidak. Bagian dari smart pointer kepemilikan akan menghapus objek jika setiap pemilik menyerahkan objek. Perilaku ini sering dibutuhkan, sehingga shared smart pointer sering digunakan secara luas.
Beberapa orang yang memiliki smart pointer tidak mendukung yang kedua maupun yang ketiga. Karena itu mereka tidak dapat dikembalikan dari fungsi atau dilewatkan di tempat lain. Yang paling cocok untuk RAII
tujuan di mana pointer cerdas disimpan lokal dan baru saja dibuat sehingga membebaskan objek setelah keluar dari ruang lingkup.
Pangsa kepemilikan dapat diimplementasikan dengan memiliki copy constructor. Ini secara alami menyalin pointer cerdas dan baik salinan maupun aslinya akan merujuk objek yang sama. Transfer kepemilikan tidak dapat benar-benar diterapkan dalam C ++ saat ini, karena tidak ada cara untuk mentransfer sesuatu dari satu objek ke yang lain yang didukung oleh bahasa: Jika Anda mencoba mengembalikan objek dari suatu fungsi, yang terjadi adalah objek tersebut disalin. Jadi penunjuk cerdas yang mengimplementasikan transfer kepemilikan harus menggunakan copy constructor untuk mengimplementasikan transfer kepemilikan tersebut. Namun, ini pada gilirannya memecah penggunaannya dalam wadah, karena persyaratan menyatakan perilaku tertentu dari copy constructor elemen kontainer yang tidak sesuai dengan perilaku yang disebut "moving constructor" dari smart pointer ini.
C ++ 1x memberikan dukungan asli untuk transfer kepemilikan dengan memperkenalkan apa yang disebut "memindahkan konstruktor" dan "memindahkan operator penugasan". Ini juga dilengkapi dengan smart pointer transfer kepemilikan yang disebut unique_ptr
.
scoped_ptr
adalah penunjuk cerdas yang tidak dapat ditransfer atau dibagikan. Ini hanya dapat digunakan jika Anda secara lokal perlu mengalokasikan memori, tetapi pastikan itu dibebaskan lagi ketika keluar dari ruang lingkup. Tetapi masih dapat ditukar dengan scoped_ptr lain, jika Anda ingin melakukannya.
shared_ptr
adalah penunjuk cerdas yang membagi kepemilikan (jenis ketiga di atas). Referensi dihitung sehingga dapat melihat kapan salinan terakhir keluar dari ruang lingkup dan kemudian membebaskan objek yang dikelola.
weak_ptr
adalah penunjuk cerdas yang tidak memiliki. Ini digunakan untuk mereferensikan objek yang dikelola (dikelola oleh shared_ptr) tanpa menambahkan jumlah referensi. Biasanya, Anda harus mengeluarkan pointer mentah dari shared_ptr dan menyalinnya. Tapi itu tidak akan aman, karena Anda tidak akan memiliki cara untuk memeriksa kapan objek itu benar-benar dihapus. Jadi, lemah_ptr menyediakan sarana dengan mereferensikan objek yang dikelola oleh shared_ptr. Jika Anda perlu mengakses objek, Anda bisa mengunci manajemennya (untuk menghindari itu di utas lain shared_ptr membebaskannya saat Anda menggunakan objek) dan kemudian menggunakannya. Jika lemah_ptr menunjuk ke suatu objek yang sudah dihapus, ia akan melihat Anda dengan melemparkan pengecualian. Menggunakan lemah_ptr paling bermanfaat ketika Anda memiliki referensi siklik: Menghitung referensi tidak dapat dengan mudah mengatasi situasi seperti itu.
intrusive_ptr
seperti shared_ptr tetapi tidak menyimpan penghitungan referensi dalam shared_ptr tetapi membiarkan penambahan / pengurangan jumlah ke beberapa fungsi pembantu yang perlu didefinisikan oleh objek yang dikelola. Ini memiliki keuntungan bahwa objek yang sudah direferensikan (yang memiliki jumlah referensi bertambah dengan mekanisme penghitungan referensi eksternal) dapat dimasukkan ke dalam intrusive_ptr - karena jumlah referensi tidak lagi internal ke penunjuk pintar, tetapi penunjuk pintar menggunakan yang sudah ada mekanisme penghitungan referensi.
unique_ptr
adalah transfer pointer kepemilikan. Anda tidak bisa menyalinnya, tetapi Anda bisa memindahkannya dengan menggunakan konstruktor gerakan C ++ 1x:
unique_ptr<type> p(new type);
unique_ptr<type> q(p); // not legal!
unique_ptr<type> r(move(p)); // legal. p is now empty, but r owns the object
unique_ptr<type> s(function_returning_a_unique_ptr()); // legal!
Ini adalah semantik yang std :: auto_ptr taat, tetapi karena kehilangan dukungan asli untuk bergerak, gagal menyediakannya tanpa jebakan. unique_ptr akan secara otomatis mencuri sumber daya dari temporary_ptr lain sementara yang merupakan salah satu fitur kunci semantik bergerak. auto_ptr akan ditinggalkan dalam rilis C ++ Standard berikutnya yang mendukung unique_ptr. C ++ 1x juga akan memungkinkan benda isian yang hanya bergerak tetapi tidak dapat disalin ke dalam wadah. Jadi Anda dapat memasukkan unik_ptr ke vektor misalnya. Saya akan berhenti di sini dan merujuk Anda ke artikel bagus tentang ini jika Anda ingin membaca lebih lanjut tentang ini.
auto_ptr
sudah usang (C ++ 11).
intrusive_ptr
lebih baik shared_ptr
untuk koherensi cache yang lebih baik. Tampaknya cache berkinerja lebih baik jika Anda menyimpan jumlah referensi sebagai bagian dari memori objek yang dikelola itu sendiri, bukan objek yang terpisah. Ini dapat diimplementasikan dalam templat atau superclass dari objek yang dikelola.
scoped_ptr adalah yang paling sederhana. Ketika keluar dari ruang lingkup, itu dihancurkan. Kode berikut ini ilegal (scoped_ptrs tidak dapat disalin) tetapi akan menggambarkan suatu hal:
std::vector< scoped_ptr<T> > tPtrVec;
{
scoped_ptr<T> tPtr(new T());
tPtrVec.push_back(tPtr);
// raw T* is freed
}
tPtrVec[0]->DoSomething(); // accessing freed memory
shared_ptr dihitung referensi. Setiap kali salinan atau penugasan terjadi, jumlah referensi bertambah. Setiap kali destruktor instance dipecat, jumlah referensi untuk T * mentah dikurangi. Setelah 0, pointer dibebaskan.
std::vector< shared_ptr<T> > tPtrVec;
{
shared_ptr<T> tPtr(new T());
// This copy to tPtrVec.push_back and ultimately to the vector storage
// causes the reference count to go from 1->2
tPtrVec.push_back(tPtr);
// num references to T goes from 2->1 on the destruction of tPtr
}
tPtrVec[0]->DoSomething(); // raw T* still exists, so this is safe
lemah_ptr adalah referensi lemah ke pointer bersama yang mengharuskan Anda untuk memeriksa untuk melihat apakah menunjuk-untuk shared_ptr masih ada
std::vector< weak_ptr<T> > tPtrVec;
{
shared_ptr<T> tPtr(new T());
tPtrVec.push_back(tPtr);
// num references to T goes from 1->0
}
shared_ptr<T> tPtrAccessed = tPtrVec[0].lock();
if (tPtrAccessed[0].get() == 0)
{
cout << "Raw T* was freed, can't access it"
}
else
{
tPtrVec[0]->DoSomething(); // raw
}
intrusive_ptr biasanya digunakan ketika ada ptr pintar pihak ke-3 yang harus Anda gunakan. Ini akan memanggil fungsi gratis untuk menambah dan mengurangi jumlah referensi. Lihat tautan untuk meningkatkan dokumentasi untuk info lebih lanjut.
if (tPtrAccessed[0].get() == 0)
seharusnya begitu if (tPtrAccessed.get() == 0)
?
Jangan mengabaikan boost::ptr_container
survei sembarang petunjuk pintar boost. Mereka bisa sangat berharga dalam situasi di mana misalnya std::vector<boost::shared_ptr<T> >
akan terlalu lambat.
Saya kedua saran tentang melihat dokumentasi. Ini tidak seseram kelihatannya. Dan beberapa petunjuk singkat:
scoped_ptr
- pointer secara otomatis dihapus ketika keluar dari ruang lingkup. Catatan - tidak ada tugas yang mungkin, tetapi memperkenalkan tidak ada overheadintrusive_ptr
- pointer penghitungan referensi tanpa overhead smart_ptr
. Namun objek itu sendiri menyimpan jumlah referensiweak_ptr
- Bekerja bersama dengan shared_ptr
untuk menangani situasi yang mengakibatkan ketergantungan melingkar (baca dokumentasi, dan cari di google untuk gambar yang bagus;)shared_ptr
- Penunjuk pintar generik, paling kuat (dan kelas berat) (dari yang ditawarkan oleh boost)auto_ptr
, yang memastikan bahwa objek yang ditunjuknya dihancurkan secara otomatis ketika kontrol meninggalkan ruang lingkup. Namun memiliki semantik salinan berbeda dari yang lainnya.unique_ptr
- akan datang dengan C ++ 0xTanggapan untuk mengedit: Ya