Ini adalah pertanyaan lama, dijawab, tetapi @Alexandre bertanya, "Mengapa ada orang yang mau melakukan ini?", Dan saya pikir saya mungkin memberikan contoh penggunaan yang saya pertimbangkan sore ini.
Kode Warisan. Menggunakan pointer telanjang Obj * obj dengan menghapus obj di akhir.
Sayangnya saya kadang-kadang perlu, tidak sering, untuk menjaga objek tetap hidup.
Saya mempertimbangkan untuk menjadikannya sebagai penghitung smart pointer. Tetapi akan ada banyak kode untuk diubah, jika saya harus menggunakannya di ref_cnt_ptr<Obj>
mana-mana. Dan jika Anda mencampur Obj * dan ref_cnt_ptr telanjang, Anda dapat menghapus objek secara implisit ketika ref_cnt_ptr terakhir hilang, meskipun ada Obj * masih hidup.
Jadi saya berpikir untuk membuat eksplisit_delete_ref_cnt_ptr. Yaitu sebuah referensi penghitung referensi di mana penghapusan hanya dilakukan dalam rutinitas penghapusan eksplisit. Menggunakannya di satu tempat di mana kode yang ada mengetahui umur objek, serta dalam kode baru saya yang membuat objek tetap hidup lebih lama.
Menambah dan mengurangi jumlah referensi sebagai eksplisit_delete_ref_cnt_ptr bisa dimanipulasi.
Tapi JANGAN membebaskan ketika jumlah referensi dianggap nol dalam destruktor eksplisit_delete_ref_cnt_ptr.
Hanya membebaskan ketika jumlah referensi dianggap nol dalam operasi penghapusan seperti eksplisit. Misalnya dalam sesuatu seperti:
template<typename T> class explicit_delete_ref_cnt_ptr {
private:
T* ptr;
int rc;
...
public:
void delete_if_rc0() {
if( this->ptr ) {
this->rc--;
if( this->rc == 0 ) {
delete this->ptr;
}
this->ptr = 0;
}
}
};
Oke, kira-kira seperti itu. Agak tidak biasa untuk memiliki referensi tipe pointer yang dihitung tidak secara otomatis menghapus objek yang ditunjuk di destruktor ptr rc'ed. Tapi sepertinya ini mungkin membuat campuran pointer telanjang dan pointer rc sedikit lebih aman.
Namun sejauh ini tidak perlu untuk menghapus ini.
Tapi kemudian terlintas di benak saya: jika objek menunjuk, orang yang dituju, tahu bahwa itu sedang dihitung referensi, misalnya jika jumlah berada di dalam objek (atau dalam beberapa tabel lain), maka delete_if_rc0 rutin bisa menjadi metode dari objek pointee, bukan pointer (pintar).
class Pointee {
private:
int rc;
...
public:
void delete_if_rc0() {
this->rc--;
if( this->rc == 0 ) {
delete this;
}
}
}
};
Sebenarnya, itu tidak perlu menjadi metode anggota sama sekali, tetapi bisa menjadi fungsi bebas:
map<void*,int> keepalive_map;
template<typename T>
void delete_if_rc0(T*ptr) {
void* tptr = (void*)ptr;
if( keepalive_map[tptr] == 1 ) {
delete ptr;
}
};
(BTW, saya tahu kode ini kurang tepat - menjadi kurang dapat dibaca jika saya menambahkan semua detail, jadi saya membiarkannya seperti ini.)
delete this
telah membuat kopling ketat antara kelas dan metode alokasi yang digunakan untuk membuat objek dari kelas itu. Itu adalah desain OO yang sangat buruk, karena hal yang paling mendasar dalam OOP adalah membuat kelas otonom yang tidak tahu atau peduli tentang apa yang dilakukan penelepon mereka. Dengan demikian kelas yang dirancang dengan baik seharusnya tidak tahu atau peduli tentang bagaimana itu dialokasikan. Jika Anda karena suatu alasan memerlukan mekanisme yang aneh, saya pikir desain yang lebih baik adalah dengan menggunakan kelas pembungkus di sekitar kelas yang sebenarnya, dan biarkan pembungkus berurusan dengan alokasi.