Bu eski, cevaplanmış bir soru ama @Alexandre "Neden bunu yapmak istesin ki?" Diye sordu ve bu öğleden sonra düşündüğüm örnek bir kullanım sağlayabileceğimi düşündüm.
Eski kod. Sonunda silme obj ile çıplak işaretçiler Obj * obj kullanır.
Ne yazık ki bazen nesneyi daha uzun süre canlı tutmak için sık sık olmamak gerekir.
Bir referans sayılır akıllı işaretçi yapmayı düşünüyorum. Ama ben her yerde kullanmak olsaydı, değiştirmek için kod çok olurdu ref_cnt_ptr<Obj>
. Ve çıplak Obj * ve ref_cnt_ptr'i karıştırırsanız, Obj * hala hayatta olsa bile, son ref_cnt_ptr gittiğinde nesneyi dolaylı olarak silebilirsiniz.
Bu yüzden bir explicit_delete_ref_cnt_ptr oluşturmayı düşünüyorum. Yani, silme işleminin yalnızca açık bir silme rutininde yapıldığı bir referans sayma işaretçisi. Mevcut kodun nesnenin ömrünü bildiği tek bir yerde ve nesneyi daha uzun süre canlı tutan yeni kodumda kullanmak.
Referans sayısını explicit_delete_ref_cnt_ptr olarak artırmak ve azaltmak manipüle edilir.
Ancak explicit_delete_ref_cnt_ptr yıkıcıda referans sayısı sıfır olarak göründüğünde serbest DEĞİLDİR.
Yalnızca, açık bir silme benzeri işlemde referans sayısının sıfır olduğu görülüyorsa serbest kalır. Örneğin:
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;
}
}
};
Tamam, böyle bir şey. Rc'ed ptr destructor'da gösterilen nesneyi otomatik olarak silmeyen bir referans sayılan işaretçi türüne sahip olmak alışılmadık bir durumdur. Ancak bu, çıplak işaretçiler ve rc'ed işaretçilerin karıştırılmasını biraz daha güvenli hale getirebilir.
Ama şu ana kadar bunu silmeye gerek yok.
Ama sonra benim başıma geldi: eğer nesne işaret ettiğinde, pointee, referansın sayıldığını bilir, örneğin sayım nesnenin içindeyse (veya başka bir tabloda), o zaman rutin delete_if_rc0 bir yöntem olabilir pointee nesnesi (akıllı) işaretçi değil.
class Pointee {
private:
int rc;
...
public:
void delete_if_rc0() {
this->rc--;
if( this->rc == 0 ) {
delete this;
}
}
}
};
Aslında, üye bir yöntem olması gerekmez, ancak ücretsiz bir işlev olabilir:
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, kodun oldukça doğru olmadığını biliyorum - tüm ayrıntıları eklersem daha az okunabilir hale gelir, bu yüzden böyle bırakıyorum.)
delete this
, sınıf ve o sınıfın nesnelerini oluşturmak için kullanılan ayırma yöntemi arasında sıkı bir bağlantı oluşturduysanız olurdu . Bu çok zayıf OO tasarımıdır, çünkü OOP'taki en temel şey, arayanların ne yaptığını bilmeyen veya umursamayan özerk sınıflar yapmaktır. Bu nedenle, uygun şekilde tasarlanmış bir sınıf, nasıl tahsis edildiğini bilmemeli veya önemsememelidir. Herhangi bir nedenden dolayı böyle tuhaf bir mekanizmaya ihtiyacınız varsa, daha iyi bir tasarımın gerçek sınıfın etrafında bir sarmalayıcı sınıfı kullanmak ve sarmalayıcının tahsisle baş etmesine izin vermek olduğunu düşünüyorum.