Menghapus pointer ke const (T const *)

89

Saya punya pertanyaan dasar tentang petunjuk const. Saya tidak diizinkan untuk memanggil fungsi non-anggota const menggunakan pointer const. Namun, saya diizinkan melakukan ini pada pointer const:

delete p;

Ini akan memanggil destruktor kelas yang pada dasarnya adalah 'metode' non-const. Mengapa ini diperbolehkan? Apakah hanya untuk mendukung ini:

delete this;

Atau ada alasan lain?

Naveen
sumber

Jawaban:

112

Ini untuk mendukung:

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

// use const member functions here

// delete it
delete f;

Tetapi perhatikan bahwa masalahnya tidak terbatas pada objek yang dibuat secara dinamis:

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

Jika destruktor tidak bisa dipanggil pada objek const, kami tidak dapat menggunakan objek const sama sekali.

Agnel Kurian
sumber
21
+1 untuk hasil edit Anda yang terbaru. Saya pikir ini alasan yang benar. Pemanggilan destruktor otomatis untuk objek const - hampir sama dengan delete f; di mana f - pointer pada const.
bayda
const Foo * fatau Foo const * fbukan merupakan pointer const ke Foo. Ini lebih mengarah ke const Foo. Foo * const f adalah pointer const ke Foo.
pengguna11373693
48

Begini - jika tidak diizinkan, tidak akan ada cara untuk menghapus objek const tanpa menggunakan const_cast.

Secara semantik, const adalah indikasi bahwa suatu objek harus tetap. Namun, itu tidak berarti bahwa objek tersebut tidak boleh dihapus.

PaulJWilliams
sumber
3
Destructors dapat mengubah objek dengan cara yang agak kejam, jadi ini pasti penggunaan aneh dari kata 'abadi' yang sebelumnya tidak saya sadari ...
DarthGizka
1
@DarthGizka tidak, perusak membawa Anda dari keadaan di mana ada objek, ke keadaan di mana tidak ada. C ++ tidak mendefinisikan metode apa pun untuk mengamati "mutasi" pasca penghancuran
Caleth
@ Caleth: standar mungkin tidak mengizinkan Anda untuk melihat objek setelah penghancurnya berjalan hingga selesai, tetapi Anda tentu saja diizinkan untuk melihat efek samping yang disebabkan oleh penghancuran tersebut. Karenanya, keadaan dapat dengan mudah diatur agar mutasi objek yang 'tidak berubah' dapat diamati. Di AS, pembunuhan sulit untuk dituntut jika tidak ada mayat, tetapi tetap saja pembunuhan (dan mungkin ada bukti lain yang cukup untuk membuat sebuah keyakinan). Perbedaan yang sama.
DarthGizka
6

Saya tidak diizinkan untuk memanggil fungsi non-anggota const menggunakan pointer const.

Ya, kamu.

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

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

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

Anda telah membingungkan penunjuk const ke objek non-const, dengan penunjuk non-const ke objek const.

Karena itu,

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

sah juga untuk menghapus, karena alasan yang sudah disebutkan oleh jawaban lain di sini.

Oktalis
sumber
5

Pembuat dan Penghancur tidak boleh dipandang sebagai 'metode'. Mereka adalah konstruksi khusus untuk menginisialisasi dan merobohkan objek kelas.

'const pointer' adalah untuk menunjukkan bahwa status objek tidak akan berubah ketika operasi dilakukan pada objek tersebut saat masih hidup.

Indy9000
sumber
5

Cara lain untuk melihatnya: arti yang tepat dari sebuah pointer const adalah bahwa Anda tidak akan dapat membuat perubahan pada objek yang diarahkan ke yang akan terlihat melalui itu atau pointer atau referensi lain ke objek yang sama. Namun saat sebuah objek hancur, semua penunjuk lain ke alamat yang sebelumnya ditempati oleh objek yang sekarang dihapus tidak lagi menjadi penunjuk ke objek itu . Mereka menyimpan alamat yang sama, tetapi alamat itu bukan lagi alamat objek apa pun (sebenarnya alamat itu mungkin akan segera digunakan kembali sebagai alamat objek yang berbeda).

Perbedaan ini akan lebih jelas jika pointer dalam C ++ berperilaku seperti referensi yang lemah, yaitu segera setelah objek dimusnahkan, semua pointer yang masih ada akan segera disetel ke 0. (Itu adalah jenis hal yang dianggap terlalu mahal pada waktu proses untuk diterapkan pada semua program C ++, dan pada kenyataannya tidak mungkin membuatnya sepenuhnya dapat diandalkan.)

PEMBARUAN : Membaca ini kembali sembilan tahun kemudian, itu adalah pengacara. Sekarang saya menemukan reaksi asli Anda dapat dimengerti. Untuk melarang mutasi tetapi membiarkan kehancuran jelas bermasalah. Kontrak tersirat dari pointer / referensi const adalah bahwa keberadaan mereka akan bertindak sebagai penghambat penghancuran objek target, alias pengumpulan sampah otomatis.

Solusi yang biasa untuk ini adalah dengan menggunakan hampir semua bahasa lain.

Daniel Earwicker
sumber
Jika Anda tidak dapat menghancurkan hal-hal yang ditunjukkan oleh pointer ke const, bagaimana Anda menghadapi std::unique_ptr<const T>akhir dari hidup itu?
Caleth
@Caleth maka tidak akan ada solusi untuk itu di C ++. Itu hanyalah satu contoh dari masalah umum: di C ++ pengubah const berarti "Anda tidak dapat mengubah target, kecuali dalam satu hal di mana Anda dapat sepenuhnya merusaknya dan membuat semua referensi lain ke sana menjadi tidak valid dan sumber dari perilaku yang tidak ditentukan". Inilah mengapa menurut saya pertanyaan semacam ini harus bertindak sebagai pemicu untuk mempertimbangkan bahasa lain. Ia memiliki lubang UB di dalamnya yang tidak dapat diselesaikan tanpa mengambil pendekatan dasar yang berbeda.
Daniel Earwicker