Sabit'e bir işaretçi silme (T const *)


91

Const işaretçileriyle ilgili temel bir sorum var. Const işaretçisi kullanarak const olmayan herhangi bir üye işlevi çağırma iznim yok. Bununla birlikte, bunu bir const işaretçisinde yapma iznim var:

delete p;

Bu, özünde const olmayan bir 'yöntem' olan sınıfın yıkıcısını çağıracaktır. Buna neden izin veriliyor? Sadece bunu desteklemek için mi:

delete this;

Yoksa başka bir sebep mi var?

Yanıtlar:


113

Desteklemek için:

// dynamically create object that cannot be changed
const Foo * f = new Foo;

// use const member functions here

// delete it
delete f;

Ancak sorunun dinamik olarak oluşturulan nesnelerle sınırlı olmadığını unutmayın:

{
 const Foo f;
 // use it
} // destructor called here

Eğer yıkıcılar const nesnelerinde çağrılamazsa, const nesnelerini hiç kullanamazdık.


21
En son düzenlemeniz için +1. Bunun gerçek neden olduğunu düşünüyorum. Const nesnesi için otomatik yıkıcı çağrısı - neredeyse delete f ile aynı; nerede f - sabit üzerinde işaretçi.
bayda

const Foo * fveya Foo const * fFoo'ya sabit bir gösterici değildir. Bu Foo kurşunu işaret ediyor. Foo * const f Foo'ya sabit bir göstericidir.
user11373693

48

Bu şekilde koymak - bu eğer değildi izin const_cast kullanmadan silme const nesneler yolu yoktur olurdu.

Anlamsal olarak const, bir nesnenin değişmez olması gerektiğinin bir göstergesidir. Ancak bu, nesnenin silinmemesi gerektiği anlamına gelmez.


3
Yıkıcılar, nesneleri oldukça şiddetli şekillerde değiştirebilirler, bu yüzden bu, daha önce farkında olmadığım 'değişmez' kelimesinin garip bir kullanımı olmalı ...
DarthGizka

1
@DarthGizka hayır, yıkıcılar sizi bir nesnenin olduğu bir durumdan, olmayan bir yere götürür. C ++, yıkım sonrası bir "mutasyonu" gözlemlemek için herhangi bir yöntem tanımlamaz
Caleth

@ Caleth: Standart, yıkıcısı tamamlandıktan sonra nesneye bakmanıza izin vermeyebilir, ancak kesinlikle yıkımın neden olduğu yan etkilere bakmanıza izin verilir. Bu nedenle koşullar, 'değişmez' nesnenin mutasyonunu gözlemlenebilir kılacak şekilde kolayca düzenlenebilir. ABD'de, ceset olmadığında cinayetin kovuşturulması zordur, ancak yine de cinayettir (ve mahkumiyet için yeterli başka kanıtlar olabilir). Aynı farklılık.
DarthGizka

6

Const işaretçisi kullanarak const olmayan herhangi bir üye işlevi çağırma iznim yok.

Evet öylesin.

class Foo
{
public:
  void aNonConstMemberFunction();
};

Foo* const aConstPointer = new Foo;
aConstPointer->aNonConstMemberFunction(); // legal

const Foo* aPointerToConst = new Foo;
aPointerToConst->aNonConstMemberFunction(); // illegal

Bir const işaretçisini const olmayan bir nesneye, const nesnesine yönelik const olmayan bir işaretçiyle karıştırdınız.

Bunu söyledikten sonra,

delete aConstPointer; // legal
delete aPointerToConst; // legal

Buradaki diğer cevaplarda zaten belirtilen nedenlerden dolayı ikisini de silmek yasaldır.


5

Yapıcılar ve Yıkıcılar 'yöntemler' olarak görülmemelidir. Bir sınıfın nesnesini başlatmak ve parçalamak için özel yapılardır.

'const işaretçisi', canlı durumdayken üzerinde işlemler yapıldığında nesnenin durumunun değişmeyeceğini belirtmek içindir.


5

Buna bakmanın başka bir yolu: Bir const işaretçisinin kesin anlamı, o veya başka herhangi bir işaretçi veya aynı nesneye başvuru yoluyla görülebilecek olan işaret edilen nesnede değişiklik yapamayacağınızdır. Ancak bir nesne yok edildiğinde, silinmiş nesnenin daha önce işgal ettiği adresin diğer tüm işaretçileri artık o nesneye işaret etmez . Aynı adresi saklarlar, ancak bu adres artık herhangi bir nesnenin adresi değildir (aslında yakında farklı bir nesnenin adresi olarak yeniden kullanılabilir).

C ++ 'daki işaretçiler zayıf referanslar gibi davranırsa, yani nesne yok edilir edilmez, mevcut tüm işaretçiler hemen olarak ayarlanırsa, bu ayrım daha açık olacaktır 0. (Bu, çalışma zamanında tüm C ++ programlarına empoze edilemeyecek kadar maliyetli olduğu düşünülen türden bir şeydir ve aslında onu tamamen güvenilir hale getirmek imkansızdır.)

GÜNCELLEME : Bunu dokuz yıl sonra geri okurken, avukat gibi. Şimdi orijinal tepkinizi anlaşılır buluyorum. Mutasyona izin vermemek, ancak yıkıma izin vermek açıkça sorunludur. Const işaretçilerinin / referanslarının zımni sözleşmesi, varoluşlarının hedef nesnenin yok edilmesi üzerine bir blok olarak hareket edeceğidir, yani otomatik çöp toplama.

Bunun olağan çözümü, bunun yerine hemen hemen her dili kullanmaktır.


Eğer işaretçilerle işaret edilen şeyleri yok edemezseniz, std::unique_ptr<const T>hayatının sonuyla nasıl başa çıkarsınız?
Caleth

@Caleth, C ++ 'da buna bir çözüm olmazdı. Bu, genel problemin sadece bir örneğidir: C ++ 'da const değiştirici, "Hedefi değiştiremezsiniz, ancak bir anlamda onu tamamen mahvedemezsiniz ve ona yapılan diğer tüm referansları geçersiz ve tanımlanmamış davranış kaynakları haline getirebilirsiniz" anlamına gelir. Bu nedenle, bu tür bir sorunun diğer dilleri dikkate almaya yöneltmesi gerektiğini düşünüyorum. İçinde farklı bir temel yaklaşım uygulanmadan çözülemeyen UB delikleri vardır.
Daniel Earwicker
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.