C ++: referensi const, sebelum vs setelah tipe-specifier

145

Apa perbedaan antara argumen di:

int foo1(const Fred &arg) {
...
}

dan

int foo2(Fred const &arg) {
...
}

? Saya tidak melihat kasus ini tercakup dalam FAQ parashift.

eisbaw
sumber
2
apakah ini pertanyaan tentang gaya? "const Fred" terdengar bagus dalam bahasa Inggris, tetapi "Fred const" terlihat lebih baik bagiku.
LatinSuD
1
Pada catatan terkait, apakah ada alasan yang Fred const &arglebih disukai Fred const& arg? Saya lebih suka yang terakhir karena const&ada unit di sana yang berarti "constref", dan namanya argdipisahkan oleh blanko dari semua tipe specifier.
Frank
4
@dehmann: Tapi bukan int const& refberarti 'const ref' tetapi 'ref to const'.
Cedric H.
1
Duplikat dari: stackoverflow.com/questions/2640446/…
Michael Aaron Safyan

Jawaban:

112

Tidak ada perbedaan karena const dibaca kanan-ke-kiri berkenaan dengan &, sehingga keduanya mewakili referensi ke instance Fred yang tidak dapat diubah.

Fred& constberarti referensi itu sendiri tidak dapat diubah, yang berlebihan ; ketika berhadapan dengan const pointer keduanya Fred const*dan Fred* constvalid tetapi berbeda.

Ini masalah gaya, tapi saya lebih suka menggunakan constsuffix karena dapat diterapkan secara konsisten termasuk fungsi anggota konst .

Sean Fausett
sumber
Lalu apa adalah titik untuk membuat std::is_const<const T&>::valuemenjadi false?
Jurang maut.7
@ abyss.7 itu referensi untuk const T; referensi bisa berubah.
Sean Fausett
125

Tingkah laku

Tidak ada perbedaan semantik antara const T&dan T const&; bahasa memperlakukan mereka sebagai tipe yang sama. (Hal yang sama berlaku untuk const T*dan T const*.)

Sebagai masalah gaya

Mengenai yang Anda lebih suka gaya, bagaimanapun, saya akan berbeda dari banyak jawaban lain dan lebih suka const T&(dan const T*):

  • const T&adalah gaya yang digunakan dalam buku Bahasa Pemrograman C ++ Stroustrup .
  • const T& adalah gaya yang digunakan dalam standar C ++ itu sendiri.
  • const T*adalah gaya yang digunakan dalam buku Bahasa Pemrograman C dari K&R .
  • const T* adalah gaya yang digunakan dalam standar C.
  • Karena faktor di atas, saya pikir const T&/ const T*memiliki cara yang lebih inersia dari T const&/ T const*. const T&/ Secara const T*empiris sepertinya jauh lebih umum bagi saya daripada T const&/ T const*di semua kode C ++ dan C yang pernah saya lihat. Saya pikir mengikuti praktik umum lebih mudah dibaca daripada mengikuti aturan parsing kanan-ke-kiri secara dogmatis.
  • Dengan T const*, sepertinya lebih mudah untuk salah menempatkan *as T* const(terutama jika orang tidak terbiasa dengannya). Sebaliknya, const* Tbukan sintaksis hukum.

Bagaimana dengan aturan parsing kanan-ke-kiri?

Mengenai seluruh argumen parsing kanan-ke-kiri yang tampaknya orang suka gunakan: seperti yang saya sebutkan dalam komentar untuk jawaban lain, const T&membaca baik-baik saja dari kanan ke kiri. Ini referensi ke konstanta T. "T" dan "konstanta" masing-masing dapat berfungsi sebagai kata sifat atau kata benda. (Selain itu, membaca T const*kanan-ke-kiri dapat menjadi ambigu karena dapat diartikan secara salah sebagai "pointer constant to T" dan bukan sebagai "pointer to constant T".)

jamesdlin
sumber
3
+1, disetujui. Saat membaca kode, lebih mudah untuk menemukan const jika baris dimulai dengan const. Aturan kanan-kiri benar-benar hanya diperlukan ketika secara manual menguraikan deklarasi tipe berbulu. Mengapa tidak mengoptimalkan untuk kasus yang paling umum? Selain itu, IMHO jika Anda menulis deklarasi tipe sehingga Anda perlu menjalankan FSM secara manual di kepala Anda, Anda melakukannya dengan salah.
Andreas Magnusson
2
-1. Terlepas dari seberapa dibenarkan kesimpulan Anda dan seberapa besar saya pribadi setuju untuk mereka, mereka tidak menjawab pertanyaan yang diajukan secara langsung. Ini membuat jawaban terbanyak kedua untuk pertanyaan sederhana muncul seperti omong kosong di luar topik tentang beberapa mesin bawah air yang berantakan, tanpa kesimpulan, tanpa jawaban langsung - tidak ada. Anda akan mendapatkan upvote saya ketika Anda menambahkan ringkasan yang jelas sederhana yang menyatakan " Tidak, tidak ada perbedaan semantik antara kedua sintaks , tetapi ada beberapa pertimbangan gaya sebagai berikut ...". Dan baru setelah itu semua peluru itu.
ulidtko
1
IMO alasannya const T&berbunyi lebih baik, adalah: 1- Kami membaca kode dari kiri ke kanan. Dan 2 - Ketika menggambarkan konsep baru kita mulai dari konsep yang lebih umum ke yang lebih spesifik. Di sini, constkata kunci lebih umum karena mengelompokkan ruang variabel ke dalam dua kategori, sedangkan tipe penspesifikasi mengelompokkannya menjadi banyak.
pooya13
"penunjuk ke" harus tetap bersama. Jadi tidak ada ambiguitas untukT const*
Dexter
13

Meskipun mereka satu dan sama, untuk mempertahankan konsistensi dengan aturan KANAN-KIRI tentang penguraian deklarasi C dan C ++, lebih baik menulisFred const &arg

Juga rujuk ini untuk mengembangkan lebih banyak pemahaman tentang deklarasi, kualifikasi dan deklarator.

Chubsdad
sumber
1
Saya lebih suka sufiks, karena ia bekerja lebih baik dengan typedefekspansi. Contoh: typedef int* pointer;, const pointer tidak const int* , itu int* const. Bentuk akhiran tidak canggung.
Matthieu M.
4
IMO const T&membaca baik dari kanan ke kiri juga; ini referensi ke konstanta T. Tdan constantmasing - masing dapat berfungsi sebagai kata sifat atau kata benda.
jamesdlin
7

Keduanya bekerja, dan inilah penjelasan dari pria yang menulisnya.
Mengutipnya:

Mengapa? Ketika saya menemukan "const" (awalnya bernama "readonly" dan memiliki "writeonly" yang sesuai), saya membiarkannya pergi sebelum atau setelah tipe karena saya dapat melakukannya tanpa ambiguitas.

Default
sumber
3

Referensi tidak bekerja dengan cara yang sama dengan pointer: untuk pointer Anda dapat memiliki 'pointer pointers' ( type * const p) dan 'pointer ke const' ( const type * patau type const * p).

Tetapi Anda tidak memiliki ini untuk referensi: referensi akan selalu merujuk ke objek yang sama; dalam pengertian itu Anda dapat mempertimbangkan bahwa 'referensi' adalah 'referensi const' (dengan cara yang sama Anda dapat memiliki 'pointer pointer').

Karenanya sesuatu seperti 'type & const ref' tidak sah. Anda hanya dapat memiliki 'referensi ke tipe' ( type &ref) dan 'referensi ke tipe konstan' ( const type &refatau type const &ref; keduanya persis sama).

Satu hal terakhir: walaupun const typeterdengar lebih benar dalam bahasa Inggris, menulis type constmemungkinkan pemahaman yang lebih sistematis tentang deklarasi "kanan ke kiri": int const & refdapat dibaca memiliki 'ref adalah referensi ke int konstan'. Atau contoh yang lebih rumit int const * const & ref:, ref adalah referensi ke pointer konstan ke int konstan.

Kesimpulan: dalam pertanyaan Anda, keduanya persis sama.

Cedric H.
sumber