Aku selalu mengacaukan bagaimana menggunakan const int*
, const int * const
dan int const *
benar. Apakah ada seperangkat aturan yang mendefinisikan apa yang bisa dan tidak bisa Anda lakukan?
Saya ingin mengetahui semua hal yang harus dan tidak boleh dilakukan dalam hal penugasan, melewati fungsi, dll.
int *(*)(char const * const)
. Mulai ke kanan dari kurung*
maka kita harus bergerak ke kiri:pointer
. Di luar parens, kita bisa bergerak kanan:pointer to function of ...
. Kemudian kita harus bergerak kiri:pointer to function of ... that returns pointer to int
. Ulangi untuk memperluas parameter (yang...
):pointer to function of (constant pointer to constant char) that returns pointer to int
. Seperti apakah deklarasi satu baris yang ekuivalen dalam bahasa yang mudah dibaca seperti Pascal?function(x:^char):^int
. Ada tipe fungsi yang menyiratkan pointer ke fungsi sehingga tidak perlu menentukannya, dan Pascal tidak menegakkan kebenaran const. Itu bisa dibaca dari kiri ke kanan.Jawaban:
Baca terbalik (didorong oleh Searah Jarum Jam / Spiral ):
int*
- pointer ke intint const *
- pointer ke const intint * const
- const pointer ke intint const * const
- const pointer ke const intSekarang yang pertama
const
bisa berada di kedua sisi tipe jadi:const int *
==int const *
const int * const
==int const * const
Jika Anda ingin menjadi sangat gila, Anda dapat melakukan hal-hal seperti ini:
int **
- pointer ke pointer ke intint ** const
- pointer const ke pointer ke intint * const *
- pointer ke pointer const ke intint const **
- pointer ke pointer ke const intint * const * const
- pointer const ke pointer const ke intDan untuk memastikan kami jelas tentang arti dari
const
:foo
adalah pointer variabel ke integer konstan. Ini memungkinkan Anda mengubah apa yang Anda tuju tetapi bukan nilai yang Anda tuju. Paling sering ini terlihat dengan string C-style di mana Anda memiliki pointer ke aconst char
. Anda dapat mengubah string mana yang Anda tuju tetapi Anda tidak dapat mengubah konten string ini. Ini penting ketika string itu sendiri berada di segmen data dari suatu program dan tidak boleh diubah.bar
adalah pointer konstan atau tetap ke nilai yang dapat diubah. Ini seperti referensi tanpa tambahan gula sintaksis. Karena fakta ini, biasanya Anda akan menggunakan referensi di mana Anda akan menggunakanT* const
pointer kecuali Anda perlu mengizinkanNULL
pointer.sumber
const int x = 0; const int *const px = &x; const int *const *const p = &px;
berfungsi dengan baik.Bagi mereka yang tidak tahu tentang Searah Jarum Jam / Spiral: Mulai dari nama variabel, gerakkan dengan jarum jam (dalam hal ini, pindah ke belakang) ke pointer atau jenis berikutnya . Ulangi sampai ekspresi berakhir.
Ini demo:
sumber
void (*signal(int, void (*fp)(int)))(int);
dari archive.is/SsfMXSaya pikir semuanya sudah dijawab di sini, tetapi saya hanya ingin menambahkan bahwa Anda harus berhati-hati
typedef
! Mereka BUKAN hanya penggantian teks.Sebagai contoh:
Jenisnya
astring
adalahchar * const
tidakconst char *
. Ini adalah salah satu alasan saya selalu cenderung untuk menempatkanconst
hak jenis, dan tidak pernah di awal.sumber
typedef int* PINT
(Saya berasumsi sesuatu yang berasal dari praktik di C dan banyak pengembang terus melakukannya). Hebat, saya menggantinya*
dengan aP
, itu tidak mempercepat mengetik, ditambah memperkenalkan masalah yang Anda sebutkan.PINT
memang penggunaan yang agak bodoh dari typedef, terutama karena itu membuat saya berpikir bahwa sistem toko menggunakan bir untuk memori. typedef s cukup berguna untuk menangani pointer ke fungsi.PVOID
,LPTSTR
hal-hal di api Win32!Seperti hampir semua orang tunjukkan:
Apa bedanya
const X* p
,X* const p
danconst X* const p
?sumber
const X* p;
==X const * p;
seperti pada"p points to an X that is const": the X object can't be changed via p.
Referensi konstan:
Referensi ke variabel (di sini int), yang konstan. Kami melewatkan variabel sebagai referensi terutama, karena ukuran referensi lebih kecil daripada nilai sebenarnya, tetapi ada efek samping dan itu karena itu seperti alias ke variabel aktual. Kami mungkin secara tidak sengaja mengubah variabel utama melalui akses penuh kami ke alias, jadi kami membuatnya konstan untuk mencegah efek samping ini.
Pointer konstan
Setelah pointer konstan menunjuk ke suatu variabel maka itu tidak dapat menunjuk ke variabel lain.
Pointer ke konstan
Sebuah penunjuk yang melaluinya orang tidak dapat mengubah nilai suatu variabel yang dikenal sebagai penunjuk menjadi konstan.
Pointer konstan ke konstanta
Pointer konstan ke konstanta adalah pointer yang tidak dapat mengubah alamat yang ditunjuknya dan juga tidak dapat mengubah nilai yang disimpan di alamat itu.
sumber
Aturan umum adalah bahwa
const
kata kunci berlaku untuk apa yang mendahuluinya segera. Pengecualian, permulaanconst
berlaku untuk hal-hal berikut.const int*
sama denganint const*
dan berarti "pointer ke int konstan" .const int* const
sama denganint const* const
dan berarti "pointer konstan ke int konstan" .Sunting: Untuk Dos dan Larangan, jika jawaban ini tidak cukup, dapatkah Anda lebih tepat tentang apa yang Anda inginkan?
sumber
Pertanyaan ini menunjukkan dengan tepat mengapa saya suka melakukan hal-hal seperti yang saya sebutkan dalam pertanyaan saya adalah const setelah jenis id dapat diterima?
Singkatnya, saya menemukan cara termudah untuk mengingat aturannya adalah "const" mengejar hal yang berlaku. Jadi dalam pertanyaan Anda, "int const *" berarti int adalah konstan, sedangkan "int * const" akan berarti bahwa pointernya konstan.
Jika seseorang memutuskan untuk meletakkannya di bagian paling depan (misalnya: "const int *"), sebagai pengecualian khusus dalam kasus itu berlaku untuk hal setelah itu.
Banyak orang suka menggunakan pengecualian khusus itu karena mereka pikir itu terlihat lebih bagus. Saya tidak menyukainya, karena itu pengecualian, dan karenanya membingungkan banyak hal.
sumber
const T*
dan itu menjadi lebih alami. Seberapa sering Anda menggunakanT* const
anyways, biasanya referensi akan baik-baik saja. Saya mendapat sedikit dari semua ini ketika inginboost::shared_ptr<const T>
dan bukannya menulisconst boost::shared_ptr<T>
. Masalah yang sama dalam konteks yang sedikit berbeda.const
adalah tipe yang const, dan segala yang di sebelah kanan adalah const yang sebenarnya. Ambilint const * const * p;
sebagai contoh. Tidak, saya biasanya tidak menulis seperti itu, ini hanya sebuah contoh. Pertamaconst
: ketik int, Dan int yang adalah const adalah isi dari pointer const yang merupakan isi darip
. Kedua const: type adalah pointer keconst
int, const oblect adalah isi darip
Penggunaan Sederhana
const
.Penggunaan paling sederhana adalah mendeklarasikan konstanta bernama. Untuk melakukan ini, satu menyatakan konstanta seolah-olah itu variabel tetapi tambahkan
const
sebelumnya. Kita harus segera menginisialisasi di konstruktor karena, tentu saja, kita tidak dapat menetapkan nilai nanti karena itu akan mengubahnya. Sebagai contoh:akan membuat konstanta integer, tidak terbayangkan dipanggil
Constant1
, dengan nilai 96.Konstanta semacam itu berguna untuk parameter yang digunakan dalam program tetapi tidak perlu diubah setelah program dikompilasi. Ini memiliki keuntungan bagi programmer daripada preprocessor C
#define
perintah dalam hal itu dipahami & digunakan oleh kompiler itu sendiri, tidak hanya diganti ke dalam teks program oleh preprocessor sebelum mencapai kompilator utama, sehingga pesan kesalahan jauh lebih bermanfaat.Ini juga berfungsi dengan pointer tetapi kita harus berhati-hati di mana
const
menentukan apakah pointer atau apa yang menunjuk adalah konstan atau keduanya. Sebagai contoh:menyatakan bahwa
Constant2
pointer variabel ke integer konstan dan:adalah sintaks alternatif yang melakukan hal yang sama, sedangkan
menyatakan bahwa
Constant3
adalah pointer konstan ke variabel integer danmenyatakan itu
Constant4
adalah pointer konstan ke integer konstan. Pada dasarnya 'const' berlaku untuk apa pun yang ada di sebelah kirinya (selain jika tidak ada di sana dalam hal ini berlaku untuk apa pun yang merupakan hak langsungnya).ref: http://duramecho.com/ComputerInformation/WhyHowCppConst.html
sumber
Saya memiliki keraguan yang sama seperti Anda sampai saya menemukan buku ini oleh C ++ Guru Scott Meyers. Rujuk Item ketiga dalam buku ini di mana ia berbicara secara rinci tentang penggunaan
const
.Ikuti saja saran ini
const
muncul di sebelah kiri tanda bintang, yang ditunjukkan adalah konstanconst
muncul di sebelah kanan tanda bintang, penunjuk itu sendiri konstanconst
muncul di kedua sisi, keduanya konstansumber
Sederhana tapi rumit. Harap dicatat bahwa kami dapat menukar
const
kualifikasi dengan jenis data (int
,char
,float
, dll).Mari kita lihat contoh di bawah ini.
const int *p
==>*p
read-only [p
adalah pointer ke integer konstan]int const *p
==>*p
read-only [p
adalah pointer ke integer konstan]int *p const
==> Pernyataan Salah . Compiler melempar kesalahan sintaksis.int *const p
==>p
read-only [p
adalah pointer konstan ke integer]. Karena pointer dip
sini hanya baca, deklarasi dan definisi harus berada di tempat yang sama.const int *p const
==> Pernyataan Salah . Compiler melempar kesalahan sintaksis.const int const *p
==>*p
hanya-bacaconst int *const p1
==>*p
danp
hanya-baca [p
adalah pointer konstan ke integer konstan]. Karena pointer dip
sini hanya baca, deklarasi dan definisi harus berada di tempat yang sama.int const *p const
==> Pernyataan Salah . Compiler melempar kesalahan sintaksis.int const int *p
==> Pernyataan Salah . Compiler melempar kesalahan sintaksis.int const const *p
==>*p
hanya-baca dan setara denganint const *p
int const *const p
==>*p
danp
hanya-baca [p
adalah pointer konstan ke integer konstan]. Karena pointer dip
sini hanya baca, deklarasi dan definisi harus berada di tempat yang sama.sumber
Ada banyak titik halus lainnya seputar kebenaran const di C ++. Saya kira pertanyaan di sini hanyalah tentang C, tapi saya akan memberikan beberapa contoh terkait karena tag tersebut adalah C ++:
Anda sering memberikan argumen besar seperti string
TYPE const &
yang mencegah objek dari modifikasi atau disalin. Contoh:TYPE& TYPE::operator=(const TYPE &rhs) { ... return *this; }
Tetapi
TYPE & const
tidak ada artinya karena referensi selalu const.Anda harus selalu memberi label metode kelas yang tidak mengubah kelas sebagai
const
, jika tidak, Anda tidak dapat memanggil metode dariTYPE const &
referensi. Contoh:bool TYPE::operator==(const TYPE &rhs) const { ... }
Ada situasi umum di mana nilai pengembalian dan metode harus berupa const. Contoh:
const TYPE TYPE::operator+(const TYPE &rhs) const { ... }
Bahkan, metode const tidak boleh mengembalikan data kelas internal sebagai referensi-ke-non-const.
Akibatnya, kita harus sering membuat kedua metode const dan non-const menggunakan overloading const. Misalnya, jika Anda mendefinisikan
T const& operator[] (unsigned i) const;
, maka Anda mungkin juga menginginkan versi non-const yang diberikan oleh:inline T& operator[] (unsigned i) { return const_cast<char&>( static_cast<const TYPE&>(*this)[](i) ); }
Afaik, tidak ada fungsi const di C, fungsi non-anggota tidak dapat dengan sendirinya menjadi const di C ++, metode const mungkin memiliki efek samping, dan kompiler tidak dapat menggunakan fungsi const untuk menghindari panggilan fungsi ganda. Bahkan, bahkan
int const &
referensi sederhana dapat menyaksikan nilai yang dirujuk diubah di tempat lain.sumber
Sintaks deklarasi C dan C ++ telah berulang kali dideskripsikan sebagai percobaan yang gagal, oleh desainer asli.
Sebagai gantinya, beri nama tipe "pointer to
Type
"; Saya akan menyebutnyaPtr_
:Sekarang
Ptr_<char>
adalah pointer kechar
.Ptr_<const char>
adalah penunjuk keconst char
.Dan
const Ptr_<const char>
adalahconst
pointer keconst char
.Sana.
sumber
Bagi saya, posisi
const
yaitu apakah muncul ke KIRI atau KANAN atau pada KIRI dan KANAN relatif terhadap*
membantu saya mencari tahu arti sebenarnya.A
const
ke KIRI dari*
menunjukkan bahwa objek yang ditunjuk oleh pointer adalahconst
objek.A
const
hingga HAK*
menunjukkan bahwa pointer adalahconst
pointer.Tabel berikut diambil dari Stanford CS106L Standard C ++ Programming Laboratory Reader Reader.
sumber
Ini sebagian besar membahas baris kedua: praktik terbaik, tugas, parameter fungsi dll.
Latihan umum. Cobalah untuk membuat segala
const
yang Anda bisa. Atau dengan kata lain, buat semuanyaconst
untuk memulai, dan kemudian hapus set minimumconst
diperlukan untuk memungkinkan program berfungsi. Ini akan sangat membantu dalam mencapai pembenaran yang benar, dan akan membantu memastikan bahwa bug halus tidak diperkenalkan ketika orang mencoba dan menetapkan hal-hal yang seharusnya tidak mereka modifikasi.Hindari const_cast <> seperti wabah. Ada satu atau dua kasus penggunaan yang sah untuk itu, tetapi mereka sangat sedikit dan jarang. Jika Anda mencoba mengubah
const
objek, Anda akan melakukan jauh lebih baik untuk menemukan siapa pun yang menyatakannyaconst
pada langkah pertama dan membicarakannya dengan mereka untuk mencapai konsensus tentang apa yang harus terjadi.Yang mengarah ke tugas dengan sangat rapi. Anda dapat menetapkan ke dalam sesuatu hanya jika itu non-const. Jika Anda ingin menetapkan sesuatu yang const, lihat di atas. Ingatlah bahwa dalam deklarasi
int const *foo;
danint * const bar;
hal-hal yang berbedaconst
- jawaban lain di sini telah membahas masalah itu dengan mengagumkan, jadi saya tidak akan membahasnya.Parameter fungsi:
Lewati nilai: mis.
void func(int param)
Anda tidak peduli dengan satu atau lain cara di situs panggilan. Argumen dapat dibuat bahwa ada kasus penggunaan untuk mendeklarasikan fungsi sebagaivoid func(int const param)
tetapi yang tidak berpengaruh pada pemanggil, hanya pada fungsi itu sendiri, dalam nilai apa pun yang dilewatkan tidak dapat diubah oleh fungsi selama panggilan.Lulus dengan referensi: mis.
void func(int ¶m)
Sekarang itu membuat perbedaan. Seperti yang baru saja dinyatakanfunc
diizinkan untuk berubahparam
, dan situs panggilan apa pun harus siap untuk menghadapi konsekuensinya. Mengubah deklarasi untukvoid func(int const ¶m)
mengubah kontrak, dan jaminan yangfunc
sekarang tidak dapat berubahparam
, berarti apa yang disahkan adalah apa yang akan keluar. Seperti yang telah dicatat orang lain, ini sangat berguna untuk melewati benda besar yang tidak ingin Anda ubah dengan murah. Melewati referensi jauh lebih murah daripada melewatkan objek besar berdasarkan nilai.Lewati dengan penunjuk: misalnya
void func(int *param)
danvoid func(int const *param)
Keduanya cukup identik dengan rekan referensi mereka, dengan peringatan bahwa fungsi yang dipanggil sekarang perlu diperiksanullptr
kecuali beberapa jaminan kontrak lainnya memastikanfunc
bahwa ia tidak akan pernah menerimanullptr
inparam
.Sepotong opini tentang topik itu. Membuktikan kebenaran dalam kasus seperti ini sangat sulit, terlalu mudah untuk membuat kesalahan. Jadi jangan mengambil risiko, dan selalu periksa parameter pointer untuk
nullptr
. Anda akan menyelamatkan diri dari rasa sakit dan penderitaan dan sulit menemukan serangga dalam jangka panjang. Dan untuk biaya pemeriksaan, ini sangat murah, dan dalam kasus-kasus di mana analisis statis yang dibangun dalam kompiler dapat mengelolanya, pengoptimal akan tetap melakukannya. Aktifkan Tautan Pembuatan Kode Waktu untuk MSVC, atau WOPR (saya pikir) untuk GCC, dan Anda akan membuatnya lebar program, yaitu bahkan dalam pemanggilan fungsi yang melintasi batas modul kode sumber.Pada akhir hari semua hal di atas membuat kasus yang sangat solid untuk selalu lebih suka referensi ke petunjuk. Mereka semua lebih aman.
sumber
Const dengan int di kedua sisi akan membuat pointer ke int konstan :
atau:
const
setelah itu*
akan membuat pointer konstan ke int :Dalam hal ini semua ini adalah pointer ke integer konstan , tetapi tidak satupun dari ini adalah pointer konstan:
Dalam hal ini semua adalah pointer ke integer konstan dan ptr2 adalah pointer konstan ke integer konstan . Tapi ptr1 bukan pointer konstan:
sumber
const
adalah ke kiri dari*
, mengacu pada nilai (tidak peduli apakah ituconst int
atauint const
)const
adalah di sebelah kanan dari*
, itu mengacu pada pointer itu sendiriPoin penting:
const int *p
tidak berarti nilai yang Anda maksud adalah konstan !! . Ini berarti bahwa Anda tidak dapat mengubahnya melalui pointer itu (artinya, Anda tidak dapat menetapkan $ * p = ... `). Nilai itu sendiri dapat diubah dengan cara lain. MisalnyaIni dimaksudkan untuk digunakan sebagian besar dalam tanda tangan fungsi, untuk menjamin bahwa fungsi tidak dapat secara tidak sengaja mengubah argumen yang disahkan.
sumber
Hanya demi kelengkapan untuk C mengikuti penjelasan yang lain, tidak yakin untuk C ++.
x
Pointer
int *p;
int const *p;
int * const p;
int const * const p;
Pointer ke pointer
int **pp;
int ** const pp;
int * const *pp;
int const **pp;
int * const * const pp;
int const ** const pp;
int const * const *pp;
int const * const * const pp;
N-level Dereferensi
Teruslah berjalan, tetapi semoga manusia mengucilkan Anda.
sumber
const int*
- penunjuk keint
objek konstan .Anda dapat mengubah nilai pointer; Anda tidak dapat mengubah nilai
int
objek, pointer menunjuk ke.const int * const
- pointer konstan keint
objek konstan .Anda tidak dapat mengubah nilai pointer atau nilai
int
objek yang ditunjuk pointer.int const *
- penunjuk keint
objek konstan .Pernyataan ini setara dengan 1.
const int*
- Anda dapat mengubah nilai pointer tetapi Anda tidak dapat mengubah nilaiint
objek, pointer menunjuk ke.Sebenarnya, ada opsi ke-4:
int * const
- pointer konstan keint
objek.Anda dapat mengubah nilai objek yang ditunjuk oleh pointer tetapi Anda tidak dapat mengubah nilai pointer itu sendiri. Pointer akan selalu mengarah ke
int
objek yang sama tetapi nilaiint
objek ini dapat diubah.Jika Anda ingin menentukan tipe C atau C ++ construct tertentu, Anda dapat menggunakan Aturan Searah / Spiral yang dibuat oleh David Anderson; tetapi tidak bingung dengan Anderson`s Rule yang dibuat oleh Ross J. Anderson, yang merupakan sesuatu yang sangat berbeda.
sumber