Jawaban:
Baca ini: https://isocpp.org/wiki/faq/const-correctness
Cara terakhir const
bahwa fungsi Method3
tersebut tidak mengubah anggota kelasnya yang tidak dapat diubah.
const int* const
berarti 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* const
kecuali bahwa itu mungkin kurang efisien karena pointer adalah tipe data lama biasa (POD) dan ini harus, secara umum diteruskan oleh nilai.
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 int
ke kiri adalah const
(tidak boleh diubah untuk memiliki nilai yang berbeda).
# 2 mengatakan bahwa penunjuk ke kiri adalah const
.
# 1 mengatakan bahwa int
ke kiri adalah const
.
Menyatukan semuanya, Anda bisa membaca ini sebagai const
fungsi anggota bernama Method3
yang mengambil referensi ke const
pointer ke int const
(atau const int
, jika Anda lebih suka) dan mengembalikan const
pointer ke int const
( const int
).
(Nb # 2 sepenuhnya berlebihan .)
Pertama-tama const T
sama dengan T const
.
const int* const
oleh karena itu setara dengan int const * const
.
Saat membaca ekspresi dengan banyak const
token 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 const
tidak 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 const
dan referensi serta pointer menempati penyimpanan yang sama sehingga tidak ada penghematan ruang juga.
Yang terakhir const
menunjukkan bahwa metode tersebut tidak mengubah this
objek. The this
pointer dalam tubuh metode akan memiliki (teoritis) deklarasi T const * const this
. Ini berarti bahwa suatu const T*
objek akan dapat dipanggil T::Method3()
.
const
s pertama di bagian depan frasa. Inilah tepatnya mengapa saya pikir itu adalah praktik yang buruk untuk meletakkannya di const
sana, meskipun bahasanya memungkinkan, dan ini adalah penggunaan yang paling umum.
Cara mudah untuk mengingat aturan const
adalah dengan memikirkannya seperti ini: const
berlaku 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 int
dan 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 int
ekspresi ini berlebihan dan karena itu tidak valid.
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 */
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&) const
juga 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 int
dan mengembalikan sebuah pointer konstan ke sebuah konstanta int
.
Semoga ini membantu,
Jason
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 const
berupa:
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
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.
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 Method3
yang mengembalikan sebuah pointer const ke sebuah const int.
mutable
)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.
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.
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!