Menentukan penunjuk pintar apa yang akan digunakan adalah masalah kepemilikan . Ketika datang ke manajemen sumber daya, objek A memiliki objek B jika ia mengendalikan masa objek B. Misalnya, variabel anggota dimiliki oleh objek masing-masing karena masa hidup variabel anggota terkait dengan masa pakai objek. Anda memilih pointer pintar berdasarkan pada bagaimana objek dimiliki.
Perhatikan bahwa kepemilikan dalam sistem perangkat lunak terpisah dari kepemilikan karena kami akan menganggapnya di luar perangkat lunak. Misalnya, seseorang mungkin "memiliki" rumah mereka, tetapi itu tidak berarti bahwa suatu Person
objek memiliki kendali atas masa hidup suatu House
objek. Menggabungkan konsep-konsep dunia nyata ini dengan konsep perangkat lunak adalah cara yang pasti untuk memprogram diri Anda menjadi sebuah lubang.
Jika Anda memiliki kepemilikan tunggal atas objek tersebut, gunakan std::unique_ptr<T>
.
Jika Anda telah berbagi kepemilikan atas objek ...
- Jika tidak ada siklus kepemilikan, gunakan std::shared_ptr<T>
.
- Jika ada siklus, tentukan "arah" dan gunakan std::shared_ptr<T>
dalam satu arah dan std::weak_ptr<T>
lainnya.
Jika objek memiliki Anda, tetapi ada kemungkinan tidak memiliki pemilik, gunakan pointer normal T*
(misal pointer orangtua).
Jika objek memiliki Anda (atau keberadaannya dijamin), gunakan referensi T&
.
Peringatan: Waspadai biaya petunjuk pintar. Dalam lingkungan terbatas memori atau kinerja, mungkin bermanfaat untuk hanya menggunakan pointer normal dengan skema yang lebih manual untuk mengelola memori.
Biaya:
- Jika Anda memiliki deleter khusus (mis. Anda menggunakan kumpulan alokasi) maka ini akan menimbulkan overhead per pointer yang dapat dengan mudah dihindari dengan penghapusan manual.
std::shared_ptr
memiliki overhead dari kenaikan jumlah referensi pada salinan, ditambah penurunan pada penghancuran diikuti oleh cek 0-hitungan dengan penghapusan objek yang ditahan. Bergantung pada implementasinya, ini dapat mengasapi kode Anda dan menyebabkan masalah kinerja.
- Waktu kompilasi. Seperti semua templat, pointer cerdas berkontribusi negatif terhadap waktu kompilasi.
Contoh:
struct BinaryTree
{
Tree* m_parent;
std::unique_ptr<BinaryTree> m_children[2]; // or use std::array...
};
Pohon biner tidak memiliki induknya, tetapi keberadaan pohon menyiratkan keberadaan induknya (atau nullptr
untuk root), sehingga menggunakan pointer normal. Pohon biner (dengan semantik nilai) memiliki kepemilikan tunggal atas anak-anaknya, demikian pula mereka std::unique_ptr
.
struct ListNode
{
std::shared_ptr<ListNode> m_next;
std::weak_ptr<ListNode> m_prev;
};
Di sini, simpul daftar memiliki daftar berikutnya dan sebelumnya, jadi kami menentukan arah dan digunakan shared_ptr
untuk selanjutnya dan weak_ptr
untuk mematahkan siklus.