Beberapa waktu yang lalu saya menemukan beberapa kode yang menandai variabel anggota kelas dengan mutable
kata kunci. Sejauh yang saya lihat, ini memungkinkan Anda untuk memodifikasi variabel dalam suatu const
metode:
class Foo
{
private:
mutable bool done_;
public:
void doSomething() const { ...; done_ = true; }
};
Apakah ini satu-satunya penggunaan kata kunci ini atau ada lebih dari itu memenuhi mata? Saya telah menggunakan teknik ini di kelas, menandai fungsi yang boost::mutex
bisa berubah yang memungkinkan const
untuk menguncinya karena alasan keamanan, tetapi, jujur saja, rasanya seperti sedikit peretasan.
mutable
: stackoverflow.com/questions/15999123/…const
(tipe) jadi saya tidak perlu melakukan iniclass A_mutable{}; using A = A_mutable const; mutable_t<A> a;
:, jika saya ingin konst-by-default, yaitumutable A a;
(dapat diubah secara eksplisit) danA a;
(konstit implisit).Jawaban:
Ini memungkinkan diferensiasi konstanta bitwise dan konstanta logis. Konstanta logis adalah ketika suatu objek tidak berubah dengan cara yang terlihat melalui antarmuka publik, seperti contoh penguncian Anda. Contoh lain adalah kelas yang menghitung nilai saat pertama kali diminta, dan menyimpan hasilnya.
Karena c ++ 11
mutable
dapat digunakan pada lambda untuk menyatakan bahwa hal-hal yang ditangkap oleh nilai dapat dimodifikasi (tidak secara default):sumber
x
di dalam lambda tetap di dalam lambda, yaitu fungsi lambda hanya dapat memodifikasi salinannya sendirix
. Perubahan tidak terlihat di luar, aslinyax
masih tidak berubah. Pertimbangkan bahwa lambdas diimplementasikan sebagai kelas functor; variabel yang ditangkap sesuai dengan variabel anggota.Kata
mutable
kunci adalah cara untuk menembusconst
selubung yang Anda gantungkan pada objek Anda. Jika Anda memiliki referensi const atau pointer ke suatu objek, Anda tidak dapat memodifikasi objek itu dengan cara apa pun kecuali kapan dan bagaimana itu ditandaimutable
.Dengan
const
referensi atau penunjuk, Anda dibatasi untuk:const
.The
mutable
pengecualian membuatnya begitu Anda sekarang dapat menulis atau anggota kumpulan data yang ditandaimutable
. Itulah satu-satunya perbedaan yang terlihat secara eksternal.Secara internal,
const
metode yang terlihat oleh Anda juga dapat menulis ke anggota data yang ditandaimutable
. Pada dasarnya cadar itu ditusuk secara komprehensif. Terserah sepenuhnya kepada perancang API untuk memastikan bahwamutable
tidak merusakconst
konsep dan hanya digunakan dalam kasus khusus yang bermanfaat. Katamutable
kunci membantu karena dengan jelas menandai anggota data yang tunduk pada kasus khusus ini.Dalam praktiknya Anda dapat menggunakan secara
const
obsesif di seluruh basis kode Anda (Anda pada dasarnya ingin "menginfeksi" basis kode Anda denganconst
"penyakit"). Di dunia ini, petunjuk dan rujukan adalahconst
dengan sangat sedikit pengecualian, menghasilkan kode yang lebih mudah untuk dipikirkan dan dipahami. Untuk penyimpangan yang menarik lihat "transparansi referensial".Tanpa
mutable
kata kunci, Anda pada akhirnya akan dipaksa untuk menggunakanconst_cast
berbagai kasus khusus yang berguna yang dibolehkannya (caching, penghitungan referensi, data debug, dll.). Sayangnyaconst_cast
secara signifikan lebih merusak daripadamutable
karena memaksa klien API untuk menghancurkanconst
perlindungan objek yang dia gunakan. Selain itu menyebabkanconst
kerusakan luas :const_cast
ing pointer atau referensi const memungkinkan menulis tanpa terkecuali dan metode panggilan akses ke anggota yang terlihat. Sebaliknyamutable
mengharuskan perancang API untuk melakukan kontrol halus atasconst
pengecualian, dan biasanya pengecualian ini tersembunyi dalamconst
metode yang beroperasi pada data pribadi.(NB Saya merujuk pada visibilitas data dan metode beberapa kali. Saya berbicara tentang anggota yang ditandai sebagai publik vs privat atau dilindungi yang merupakan jenis perlindungan objek yang sama sekali berbeda yang dibahas di sini .)
sumber
const_cast
untuk mengubah bagian dariconst
objek menghasilkan perilaku yang tidak terdefinisi.const_cast
untuk menerapkan mutasi variabel anggota dalam suatuconst
metode, Anda tidak akan meminta klien untuk melakukan cast - Anda akan melakukannya dalam metode denganconst_cast
ingthis
. Pada dasarnya ini memungkinkan Anda memintas konstanta pada anggota sewenang-wenang di situs panggilan tertentu , sementaramutable
mari Anda menghapus const pada anggota tertentu di semua situs panggilan. Yang terakhir biasanya adalah apa yang Anda inginkan untuk penggunaan khusus (caching, statistik), tetapi kadang-kadang const_cast sesuai dengan pola.const_cast
pola tidak cocok lebih baik dalam beberapa kasus, seperti ketika Anda ingin sementara memodifikasi anggota, kemudian mengembalikannya (cukup banyak sepertiboost::mutex
). Metode ini secara logis const karena kondisi akhir sama dengan yang awal, tetapi Anda ingin membuat perubahan sementara.const_cast
dapat berguna di sana karena memungkinkan Anda membuang const secara khusus dalam metode yang Anda mutasi akan dibatalkan, tetapimutable
tidak akan sesuai karena akan menghapus perlindungan const dari semua metode, yang tidak harus semua mengikuti "do , batalkan "pola.const_cast
bom waktu menjadi mungkin.mutable
tidak memiliki masalah seperti itu karena objek tersebut tidak dapat ditempatkan dalam memori hanya baca.Penggunaan Anda dengan boost :: mutex tepat untuk tujuan kata kunci ini. Penggunaan lain adalah untuk cache hasil internal untuk mempercepat akses.
Pada dasarnya, 'bisa berubah' berlaku untuk setiap atribut kelas yang tidak mempengaruhi keadaan objek yang terlihat secara eksternal.
Dalam kode sampel dalam pertanyaan Anda, bisa berubah-ubah mungkin tidak sesuai jika nilai done_ mempengaruhi status eksternal, itu tergantung pada apa yang ada di ...; bagian.
sumber
Mutable adalah untuk menandai atribut tertentu yang dapat dimodifikasi dari dalam
const
metode. Itulah satu-satunya tujuan. Pikirkan baik-baik sebelum menggunakannya, karena kode Anda mungkin akan lebih bersih dan lebih mudah dibaca jika Anda mengubah desain daripada menggunakannyamutable
.http://www.highprogrammer.com/alan/rants/mutable.html
Contoh yang penulis berikan meliputi variabel cache dan debugging sementara.
sumber
mutable
dapat membuat kode lebih mudah dibaca dan bersih. Dalam contoh berikut ini,read
bisaconst
seperti yang diharapkan. `mutable m_mutex; Kontainer m_container; membatalkan penambahan (Item item) {Lockguard lock (m_mutex); m_container.pushback (item); } Item read () const {Lockguard lock (m_mutex); return m_container.first (); } `Ini berguna dalam situasi di mana Anda memiliki kondisi internal tersembunyi seperti cache. Sebagai contoh:
Dan kemudian Anda dapat memiliki
const HashTable
objek yang masih menggunakanlookup()
metodenya, yang memodifikasi cache internal.sumber
mutable
memang ada saat Anda menyimpulkan untuk memungkinkan seseorang untuk mengubah data dalam fungsi yang konstan.Maksudnya adalah bahwa Anda mungkin memiliki fungsi yang "tidak melakukan apa-apa" pada keadaan internal objek, dan jadi Anda menandai fungsinya
const
, tetapi Anda mungkin benar-benar perlu memodifikasi beberapa objek dengan cara yang tidak memengaruhi yang benar. Kegunaan.Kata kunci dapat bertindak sebagai petunjuk untuk kompiler - kompilator teoretis dapat menempatkan objek konstan (seperti global) dalam memori yang ditandai hanya baca. Adanya
mutable
petunjuk bahwa ini tidak boleh dilakukan.Berikut adalah beberapa alasan yang sah untuk menyatakan dan menggunakan data yang bisa diubah:
mutable boost::mutex
sangat masuk akal.sumber
const
(dan inspeksi semacam itu akan berhasil atau gagal terlepas dariconst
ataumutable
). Cukup mendeklarasikan fungsiconst
tidak cukup: suatuconst
fungsi bebas untuk memiliki efek samping seperti memodifikasi variabel global atau sesuatu yang diteruskan ke fungsi, jadi itu bukan jaminan yang berguna untuk bukti itu.const
kata kunci dalam C ++.Ya, itulah yang dilakukannya. Saya menggunakannya untuk anggota yang dimodifikasi oleh metode yang tidak secara logis mengubah keadaan kelas - misalnya, untuk mempercepat pencarian dengan menerapkan cache:
Sekarang, Anda harus menggunakan ini dengan hati-hati - masalah konkurensi menjadi perhatian besar, karena penelepon mungkin berasumsi bahwa mereka aman jika hanya menggunakan
const
metode. Dan tentu saja, memodifikasimutable
data tidak boleh mengubah perilaku objek dengan cara yang signifikan, sesuatu yang dapat dilanggar dengan contoh yang saya berikan jika, misalnya, diharapkan bahwa perubahan yang ditulis ke disk akan segera terlihat oleh aplikasi. .sumber
Mutable digunakan ketika Anda memiliki variabel di dalam kelas yang hanya digunakan di dalam kelas itu untuk memberi sinyal hal-hal seperti misalnya mutex atau kunci. Variabel ini tidak mengubah perilaku kelas, tetapi diperlukan untuk menerapkan keamanan thread kelas itu sendiri. Jadi jika tanpa "bisa berubah", Anda tidak akan dapat memiliki fungsi "const" karena variabel ini perlu diubah di semua fungsi yang tersedia untuk dunia luar. Oleh karena itu, dapat diubah diperkenalkan untuk membuat variabel anggota dapat ditulis bahkan oleh fungsi const.
sumber
bisa berubah terutama digunakan pada detail implementasi kelas. Pengguna kelas tidak perlu tahu tentang hal itu, oleh karena itu metode yang menurutnya "harus" menjadi const. Contoh Anda memiliki mutex bisa berubah-ubah adalah contoh kanonik yang baik.
sumber
Penggunaan Anda terhadapnya bukan peretasan, meskipun seperti banyak hal dalam C ++, bisa berubah bisa menjadi peretas untuk programmer yang malas yang tidak ingin kembali lagi dan menandai sesuatu yang seharusnya tidak dianggap sebagai non-const.
sumber
Gunakan "bisa berubah" ketika untuk hal-hal yang LOGICALLY stateless kepada pengguna (dan karenanya harus memiliki "const" getter di API kelas publik) tetapi BUKAN stateless dalam IMPLEMENTASI yang mendasarinya (kode dalam .cpp Anda).
Kasus-kasus yang paling sering saya gunakan adalah inisialisasi malas dari negara-kurang "data lama polos" anggota. Yaitu, ini ideal dalam kasus-kasus sempit ketika anggota tersebut mahal untuk membangun (prosesor) atau membawa-bawa (memori) dan banyak pengguna objek tidak akan pernah meminta mereka. Dalam situasi itu Anda ingin konstruksi yang malas di bagian belakang untuk kinerja, karena 90% dari objek yang dibangun tidak akan perlu untuk membangun sama sekali, namun Anda masih perlu menyajikan API stateless yang benar untuk konsumsi publik.
sumber
Mutable mengubah arti dari
const
const bitwise ke const const untuk kelas.Ini berarti bahwa kelas-kelas dengan anggota yang bisa berubah lebih lama menjadi const bitwise dan tidak akan lagi muncul di bagian read-only dari executable.
Selain itu, ia memodifikasi pemeriksaan tipe dengan memungkinkan
const
fungsi anggota untuk mengubah anggota yang dapat berubah tanpa menggunakanconst_cast
.Lihat jawaban lain untuk perincian lebih lanjut, tetapi saya ingin menyoroti bahwa ini bukan hanya untuk tipe-aman dan itu mempengaruhi hasil kompilasi.
sumber
Dalam beberapa kasus (seperti iterator yang dirancang dengan buruk), kelas perlu menyimpan hitungan atau nilai insidental lainnya, yang tidak benar-benar mempengaruhi "keadaan" utama kelas. Ini paling sering di mana saya melihat bisa berubah digunakan. Tanpa bisa berubah, Anda akan dipaksa untuk mengorbankan seluruh keteguhan desain Anda.
Rasanya seperti hack sebagian besar waktu untuk saya juga. Berguna dalam situasi yang sangat sedikit.
sumber
Contoh klasik (seperti yang disebutkan dalam jawaban lain) dan satu-satunya situasi saya telah melihat
mutable
kata kunci yang digunakan sejauh ini, adalah untuk caching hasil dariGet
metode yang rumit , di mana cache diimplementasikan sebagai anggota data kelas dan bukan sebagai variabel statis dalam metode (untuk alasan berbagi antara beberapa fungsi atau kebersihan polos).Secara umum, alternatif untuk menggunakan
mutable
kata kunci biasanya variabel statis dalam metode atauconst_cast
triknya.Penjelasan terperinci lainnya ada di sini .
sumber
const_cast
hanya untuk ketika Anda tahu (atau telah dijamin) bahwa sesuatu tidak akan diubah (misalnya ketika mengganggu perpustakaan C) atau ketika Anda tahu itu tidak dinyatakan const. Yaitu, memodifikasi hasil variabel const-casted dalam perilaku yang tidak terdefinisi.const_cast
dapat digunakan untuk memodifikasi anggota kelas dalam suatuconst
metode, yang saya sebut ...const_cast
, seperti yang dikatakan ini hanya diperbolehkan ketika objek tidak dideklarasikanconst
. Misalnyaconst Frob f; f.something();
, denganvoid something() const { const_cast<int&>(m_foo) = 2;
hasil dalam perilaku yang tidak terdefinisi.Dapat berubah bisa berguna ketika Anda menimpa fungsi virtual const dan ingin memodifikasi variabel anggota kelas anak Anda dalam fungsi itu. Dalam sebagian besar kasus, Anda tidak ingin mengubah antarmuka kelas dasar, jadi Anda harus menggunakan variabel anggota yang dapat diubah-ubah sendiri.
sumber
Kata kunci yang dapat berubah sangat berguna saat membuat bertopik untuk tujuan pengujian kelas. Anda dapat mematikan fungsi const dan masih dapat meningkatkan (bisa berubah) penghitung atau fungsi pengujian apa pun yang telah Anda tambahkan ke rintisan Anda. Ini menjaga antarmuka kelas stubbed tetap utuh.
sumber
Salah satu contoh terbaik di mana kita menggunakan bisa berubah adalah, dalam salinan yang dalam. dalam copy constructor kami kirim
const &obj
sebagai argumen. Jadi objek baru yang dibuat akan bertipe konstan. Jika kita ingin mengubah (kebanyakan kita tidak akan berubah, dalam kasus yang jarang kita dapat mengubah) anggota dalam objek const yang baru dibuat ini kita perlu mendeklarasikannya sebagaimutable
.mutable
kelas penyimpanan hanya dapat digunakan pada anggota data kelas non-statis non-kelas. Anggota data yang dapat berubah dari suatu kelas dapat dimodifikasi bahkan jika itu adalah bagian dari objek yang dinyatakan sebagai const.Dalam contoh di atas, kita dapat mengubah nilai variabel anggota
x
meskipun itu merupakan bagian dari objek yang dinyatakan sebagai const. Ini karena variabelx
dinyatakan sebagai bisa berubah. Tetapi jika Anda mencoba mengubah nilai variabel anggotay
, kompiler akan melempar kesalahan.sumber
Kata kunci yang sangat 'berubah-ubah' sebenarnya adalah kata kunci yang dilindungi undang-undang. Sering kali kata kunci tersebut digunakan untuk memvariasikan nilai variabel konstan. Jika Anda ingin memiliki beberapa nilai konstanta, gunakan kata kunci yang dapat berubah-ubah.
sumber