C ++ Const Usage Explanation

97
const int* const Method3(const int* const&) const;

Adakah yang bisa menjelaskan penggunaan masing-masing konstanta?

RoR
sumber
27
Saya sangat menyukai metode ini untuk menguraikan deklarasi yang rumit: c-faq.com/decl/spiral.anderson.html
Jason

Jawaban:

77

Baca ini: https://isocpp.org/wiki/faq/const-correctness

Cara terakhir constbahwa fungsi Method3tersebut tidak mengubah anggota kelasnya yang tidak dapat diubah.

const int* constberarti penunjuk konstan ke int konstan: yaitu penunjuk yang tidak dapat diubah, ke int yang tidak dapat diubah: satu-satunya perbedaan antara ini dan const int&adalah bahwa itu bisanull

const int* const&Berarti referensi ke pointer konstan ke int konstan. Biasanya petunjuk tidak diberikan melalui referensi; const int* &lebih masuk akal karena itu berarti bahwa penunjuk dapat diubah selama pemanggilan metode, yang akan menjadi satu-satunya alasan saya dapat melihat untuk meneruskan penunjuk dengan referensi, const int* const&adalah untuk semua maksud dan tujuan sama seperti const int* constkecuali bahwa itu mungkin kurang efisien karena pointer adalah tipe data lama biasa (POD) dan ini harus, secara umum diteruskan oleh nilai.

satnhak
sumber
103

Lebih mudah untuk memahami jika Anda menulis ulang sebagai padanan sepenuhnya

// v───v───v───v───v───v───v───v───v───v───v───v─┬┐
//                                               ││
//  v──#1    v─#2             v──#3    v─#4      #5
   int const * const Method3(int const * const&) const;

lalu bacalah dari kanan ke kiri.

# 5 mengatakan bahwa seluruh deklarasi fungsi ke kiri adalah const, yang menyiratkan bahwa ini harus merupakan fungsi anggota daripada fungsi bebas.

# 4 mengatakan bahwa penunjuk ke kiri adalah const(tidak dapat diubah untuk menunjuk ke alamat yang berbeda).

# 3 mengatakan bahwa intke kiri adalah const(tidak boleh diubah untuk memiliki nilai yang berbeda).

# 2 mengatakan bahwa penunjuk ke kiri adalah const.

# 1 mengatakan bahwa intke kiri adalah const.

Menyatukan semuanya, Anda bisa membaca ini sebagai constfungsi anggota bernama Method3yang mengambil referensi ke constpointer ke int const(atau const int, jika Anda lebih suka) dan mengembalikan constpointer ke int const( const int).

(Nb # 2 sepenuhnya berlebihan .)

ildjarn
sumber
22

Pertama-tama const Tsama dengan T const.

const int* constoleh karena itu setara dengan int const * const.

Saat membaca ekspresi dengan banyak consttoken dan petunjuk di dalamnya, selalu coba membacanya dari kanan ke kiri (setelah menerapkan transformasi di atas). Jadi dalam hal ini nilai yang dikembalikan adalah pointer const ke sebuah constint . Membuat pointer itu sendiri consttidak masuk akal di sini karena nilai yang dikembalikan bukanlah nilai l yang dapat dimodifikasi. Membuat pointee const, bagaimanapun, menjamin bahwa pemanggil tidak boleh memodifikasi int(atau larik int) yang dikembalikan oleh Method3.

const int*const&menjadi int const*const&, jadi ini adalah referensi ke pointer const ke sebuah constint . Meneruskan pointer const dengan referensi laki-laki juga tidak masuk akal - Anda tidak dapat mengubah nilai referensi karena pointer constdan referensi serta pointer menempati penyimpanan yang sama sehingga tidak ada penghematan ruang juga.

Yang terakhir constmenunjukkan bahwa metode tersebut tidak mengubah thisobjek. The thispointer dalam tubuh metode akan memiliki (teoritis) deklarasi T const * const this. Ini berarti bahwa suatu const T*objek akan dapat dipanggil T::Method3().

Alexander Gessler
sumber
2
Memberi suara untuk ini (dan jawaban serupa dari ildjarn), sebagian untuk membuat poin bahwa semuanya lebih masuk akal jika Anda tidak menempatkan consts pertama di bagian depan frasa. Inilah tepatnya mengapa saya pikir itu adalah praktik yang buruk untuk meletakkannya di constsana, meskipun bahasanya memungkinkan, dan ini adalah penggunaan yang paling umum.
TED
12

Cara mudah untuk mengingat aturan constadalah dengan memikirkannya seperti ini: constberlaku untuk benda di sebelah kirinya, kecuali tidak ada apa pun di sebelah kirinya.

Jadi dalam kasus const int * const, konstanta pertama tidak memiliki apa pun di sebelah kirinya, jadi ini berlaku untuk intdan yang kedua memang memiliki sesuatu di sebelah kirinya, jadi ini berlaku untuk penunjuk.

Aturan ini juga memberi tahu Anda apa yang akan terjadi jika Anda memilikinya const int const *. Karena kedua konstanta berlaku untuk intekspresi ini berlebihan dan karena itu tidak valid.

Yony
sumber
3
const /* don't modify the int or array of ints' value(s) */
int* const /* as a retval, ignored. useless declaration */
Method3(const /* don't modify the int or array of ints' value(s) */
int* const /* don't modify the pointer's value, the address to which `pointer` points to. e.g. you cannot say `++pointer` */
&) const; /* this method does not modify the instance/object which implements the method */
justin
sumber
3

Saya suka menggunakan metode "jam" atau "spiral" di mana mulai dari nama pengenal (dalam hal ini Method3) Anda membaca bolak-balik dari kiri-ke-kanan-kembali-ke-kiri, dll. Untuk memecahkan kode konvensi penamaan. Begitu const int* const Method3(const int* const&) constjuga metode kelas yang tidak mengubah anggota kelas apa pun (dari beberapa kelas yang tidak bernama) dan menggunakan referensi konstan ke pointer yang menunjuk ke sebuah konstanta intdan mengembalikan sebuah pointer konstan ke sebuah konstanta int.

Semoga ini membantu,

Jason

Jason
sumber
2

Cara mudah untuk mengingat const di C ++ adalah ketika Anda melihat beberapa kode dalam bentuk seperti:

XXX const;
const YYY;

XXX, YYY akan menjadi komponen konstan,
XXX constberupa:

function ( def var ) const;    ------#1
* const;                       ------#2

const YYY bentuk:

const int;                     ------#3
const double;

Orang biasanya menggunakan tipe ini. Saat Anda melihat di "const&"suatu tempat, jangan bingung, const sedang mendeskripsikan sesuatu sebelumnya. jadi jawaban dari masalah ini sudah terbukti dengan sendirinya sekarang.

const int* const Method3(const int* const&) const;
  |          |             |          |       |
  #3         #2            #3         #2      #1
Albert Chen
sumber
2

Saya hanya ingin menyebutkan bahwa const int* const&memang referensi konstan const int*. Sebagai contoh:

int i = 0;
int j = 1;
int* p = &i;
int* q = &j;
const int* const& cpref = p;
cpref = q; //Error: assignment of read-only reference 'cpref'

Ini juga kasus untuk int* const&, Yang artinya: "Referensi konstan ke int*".
Tapi const int*&merupakan referensi non-konstan const int*.
Semoga ini membantu.

MrDetective
sumber
1

Membaca dari kanan ke kiri membuat pemahaman pengubah lebih mudah.

Sebuah metode const yang mengambil referensi ke sebuah pointer const ke sebuah const int dipanggil Method3yang mengembalikan sebuah pointer const ke sebuah const int.

  1. Metode const tidak dapat mengubah anggota (kecuali mereka secara cepat mutable)
  2. Sebuah pointer const tidak dapat diubah untuk menunjuk ke sesuatu yang lain
  3. Sebuah const int (atau tipe lainnya) tidak dapat dimodifikasi
Nick Strupat
sumber
1

const # 1: Pointer yang dikembalikan oleh Method3 mengacu pada const int.

const # 2: Nilai pointer yang dikembalikan oleh fungsi itu sendiri, adalah const. Ini adalah konstanta yang tidak berguna (meskipun secara gramatis valid), karena nilai yang dikembalikan dari suatu fungsi tidak dapat berupa nilai-l.

const # 3: Jenis pointer yang diteruskan dengan referensi ke titik fungsi ke sebuah const int.

const # 4: Nilai pointer yang diteruskan dengan referensi ke fungsi itu sendiri, adalah pointer const. Mendeklarasikan nilai yang diteruskan ke fungsi sebagai const biasanya tidak ada gunanya, tetapi nilai ini diteruskan oleh referensi, sehingga bisa bermakna.

const # 5: Fungsi (mungkin fungsi anggota) adalah const, artinya tidak diizinkan untuk (a) menetapkan nilai baru ke setiap anggota objek yang merupakan bagiannya atau (b) memanggil fungsi anggota non-konst pada objek atau salah satu anggotanya.

Jollymorphic
sumber
0
  • const di akhir metode ini adalah kualifikasi yang menandakan status objek tidak akan diubah.

  • const int*const&menandakan menerima dengan referensi sebuah pointer const ke lokasi const. Itu tidak dapat mengubah untuk menunjuk ke lokasi yang berbeda atau mengubah nilai yang dituju.

  • const int*const adalah nilai kembali yang juga merupakan penunjuk konstan ke lokasi konstan.

Mahesh
sumber
0

Beberapa contoh mungkin bagus untuk menunjukkan konsep ini, semakin banyak semakin baik.

class TestClass
{
private:
   int iValue;
   int* oValuePtr;
   int& oValueRef;

public:
   int TestClass::ByValMethod1(int Value)
   {
      // Value can be modified
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   int TestClass::ByValMethod2(const int Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   const int TestClass::ByValMethod3(int Value)
   {
      // Value can be modified
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   const int TestClass::ByValMethod4(const int Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   const int TestClass::ByValMethod5(const int Value) const
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // iValue *cannot* be modified
      // Access through a const object
      iValue = Value;
      iValue += 1;

      // Return value *cannot* be modified
      // Access through a const object
      return ++iValue;
   }

   int& TestClass::ByRefMethod1(int& Value)
   {
      // Value can be modified
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   int& TestClass::ByRefMethod2(const int& Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   const int& TestClass::ByRefMethod3(int& Value)
   {
      // Value can be modified
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   const int& TestClass::ByRefMethod4(const int& Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   const int& TestClass::ByRefMethod5(const int& Value) const
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   int* TestClass::PointerMethod1(int* Value)
   {
      // Value can be modified
      Value++;

      // oValuePtr can be assigned
      oValuePtr = Value;

      // oValuePtr can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   int* TestClass::PointerMethod2(const int* Value)
   {
      // Value can be modified
      Value++;

      // oValuePtr cannot be assigned
      // const int* to int*
      oValuePtr = Value;

      // oValuePtr can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   const int* TestClass::PointerMethod3(int* Value)
   {
      // Value can be modified
      Value++;

      // oValuePtr can be assigned
      oValuePtr = Value;

      // iValue can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   const int* TestClass::PointerMethod4(const int* Value)
   {
      // Value cannot be modified
      Value++;

      // oValuePtr *cannot* be assigned
      // const int* to int*
      oValuePtr = Value;

      // oValuePtr can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   const int* TestClass::PointerMethod5(const int* Value) const
   {
      // Value can be modified
      ++Value;

      // oValuePtr *cannot* be assigned
      // const int* to int* const
      // Access through a const object
      oValuePtr = Value;

      // oValuePtr *cannot* be modified
      // Access through a const object
      oValuePtr += 1;

      // Return value *cannot* be modified
      return ++oValuePtr;
   }
};

Saya harap ini membantu!

Rastus7
sumber