Câu trả lời:
Đọc phần này: https://isocpp.org/wiki/faq/const-correctness
Cuối cùng const
có nghĩa là hàm Method3
không sửa đổi các thành viên không thể thay đổi của lớp nó.
const int* const
có nghĩa là một con trỏ không đổi đến một hằng số int: tức là một con trỏ không thể thay đổi, đến một int không thể thay đổi: sự khác biệt duy nhất giữa điều này và const int&
là nó có thể đượcnull
const int* const&
có nghĩa là một tham chiếu đến một con trỏ hằng đến một hằng số int. Thông thường các con trỏ không được chuyển qua tham chiếu; const int* &
có ý nghĩa hơn vì nó có nghĩa là con trỏ có thể được thay đổi trong khi gọi phương thức, đó sẽ là lý do duy nhất tôi có thể thấy để chuyển một con trỏ bằng tham chiếu, const int* const&
là tất cả các ý định và mục đích giống nhau const int* const
ngoại trừ việc nó có thể kém hiệu quả hơn vì con trỏ là các loại dữ liệu cũ thuần túy (POD) và chúng nói chung phải được chuyển theo giá trị.
Sẽ dễ hiểu hơn nếu bạn viết lại nó dưới dạng hoàn toàn tương đương
// 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;
sau đó đọc nó từ phải sang trái.
# 5 nói rằng toàn bộ khai báo hàm ở bên trái const
, ngụ ý rằng đây nhất thiết phải là một hàm thành viên hơn là một hàm miễn phí.
# 4 nói rằng con trỏ bên trái là const
(có thể không được thay đổi để trỏ đến một địa chỉ khác).
# 3 nói rằng int
bên trái là const
(có thể không được thay đổi để có giá trị khác).
# 2 nói rằng con trỏ bên trái là const
.
# 1 nói rằng int
bên trái là const
.
Tổng hợp tất cả lại với nhau, bạn có thể đọc đây là một const
hàm thành viên có tên có tên Method3
tham chiếu đến một const
con trỏ đến một int const
(hoặc a const int
, nếu bạn thích) và trả về một const
con trỏ tới một int const
( const int
).
(Nb # 2 hoàn toàn không cần thiết .)
Trước hết const T
là tương đương với T const
.
const int* const
do đó tương đương với int const * const
.
Khi đọc các biểu thức có nhiều const
mã thông báo và con trỏ trong đó, hãy luôn cố gắng đọc chúng từ phải sang trái (sau khi áp dụng phép biến đổi ở trên). Vì vậy, trong trường hợp này giá trị trả về là một con trỏ const tới một constint
. Bản thân con trỏ const
không có ý nghĩa gì ở đây vì giá trị trả về không phải là một giá trị có thể được sửa đổi. const
Tuy nhiên, việc làm cho pointee đảm bảo rằng người gọi không thể sửa đổi int
(hoặc mảng các int
) được trả về bởi Method3
.
const int*const&
trở thành int const*const&
, vì vậy nó là một tham chiếu đến một con trỏ const tới một constint
. Truyền một con trỏ const bởi tham chiếu nam cũng không có ý nghĩa gì - bạn không thể sửa đổi giá trị được tham chiếu vì con trỏ là const
và các tham chiếu và con trỏ chiếm dung lượng như nhau nên cũng không tiết kiệm được dung lượng.
Cuối cùng const
chỉ ra rằng phương thức không sửa đổi this
đối tượng. Con this
trỏ trong phần thân phương thức sẽ có phần khai báo (lý thuyết) T const * const this
. Điều này có nghĩa là một const T*
đối tượng sẽ có thể gọi T::Method3()
.
const
ở đầu cụm từ. Đây chính là lý do tại sao tôi nghĩ rằng việc đặt nó ở đó là một việc làm const
không tốt, mặc dù ngôn ngữ cho phép nó và đó là cách sử dụng phổ biến nhất.
Một cách dễ dàng để nhớ các quy tắc const
là suy nghĩ về nó theo cách này: const
áp dụng cho thứ ở bên trái của nó, trừ khi không có thứ gì ở bên trái của nó.
Vì vậy, trong trường hợp const int * const
, hằng số đầu tiên không có gì ở bên trái của nó, vì vậy nó áp dụng cho int
và hằng số thứ hai không có gì đó ở bên trái, vì vậy nó áp dụng cho con trỏ.
Quy tắc này cũng cho bạn biết điều gì sẽ xảy ra trong trường hợp bạn có const int const *
. Vì cả hai const áp dụng cho int
biểu thức này là thừa và do đó không hợp lệ.
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 */
Tôi thích sử dụng phương pháp "đồng hồ" hoặc "xoắn ốc" trong đó bắt đầu từ tên mã định danh (trong trường hợp này Method3
) bạn đọc qua lại từ trái sang phải-qua lại-trái, v.v. để giải mã quy ước đặt tên. Vì vậy, const int* const Method3(const int* const&) const
một phương thức lớp không thay đổi bất kỳ thành viên lớp nào (của một số lớp chưa được đặt tên) và nhận tham chiếu không đổi đến một con trỏ trỏ đến một hằng số int
và trả về một con trỏ hằng số thành một hằng số int
.
Hi vọng điêu nay co ich,
Jason
Một cách dễ dàng để nhớ const trong C ++ là khi bạn nhìn thấy một số mã ở dạng như:
XXX const;
const YYY;
XXX, YYY sẽ là một thành phần không đổi,
XXX const
dạng:
function ( def var ) const; ------#1
* const; ------#2
const YYY
hình thức:
const int; ------#3
const double;
Mọi người thường sử dụng những loại này. Khi bạn nhìn thấy "const&"
một nơi nào đó, đừng cảm thấy bối rối, const đang mô tả một cái gì đó trước chính nó. vì vậy câu trả lời của vấn đề này là hiển nhiên bây giờ.
const int* const Method3(const int* const&) const;
| | | | |
#3 #2 #3 #2 #1
Tôi chỉ muốn đề cập rằng đó const int* const&
thực sự là một tham chiếu liên tục const int*
. Ví dụ:
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'
Nó cũng là trường hợp của int* const&
, Có nghĩa là: "Tham chiếu liên tục đến int*
".
Nhưng const int*&
là một tham chiếu không liên tục đến const int*
.
Hi vọng điêu nay co ich.
Đọc từ phải sang trái giúp hiểu các bổ ngữ dễ dàng hơn.
Một phương thức const nhận tham chiếu đến một con trỏ const tới một const int được gọi Method3
để trả về một con trỏ const tới một const int.
mutable
)const # 1: Con trỏ do Method3 trả về tham chiếu đến một int const.
const # 2: Giá trị con trỏ được trả về bởi chính hàm, là const. Đây là một hằng số vô dụng (mặc dù có giá trị về mặt vật lý), vì giá trị trả về từ một hàm không thể là giá trị l.
const # 3: Kiểu con trỏ được truyền bởi tham chiếu đến hàm trỏ đến một const int.
const # 4: Giá trị con trỏ được truyền bởi tham chiếu đến hàm, chính nó là một con trỏ const. Khai báo một giá trị được truyền cho một hàm như const thường sẽ là vô nghĩa, nhưng giá trị này được truyền bằng tham chiếu, vì vậy nó có thể có ý nghĩa.
const # 5: Hàm (có lẽ là một hàm thành viên) là const, có nghĩa là nó không được phép (a) gán giá trị mới cho bất kỳ thành viên nào của đối tượng mà nó là một phần hoặc (b) gọi một hàm thành viên không phải const trên đối tượng hoặc bất kỳ thành viên nào của nó.
const
ở cuối phương thức là ký hiệu định tính cho biết trạng thái của đối tượng sẽ không bị thay đổi.
const int*const&
biểu thị việc nhận bằng cách tham chiếu một con trỏ const đến một vị trí const. Nó không thể thay đổi để trỏ đến một vị trí khác hoặc thay đổi giá trị mà nó đang trỏ tới.
const int*const
là giá trị trả về cũng là một con trỏ không đổi đến một vị trí không đổi.
Một vài ví dụ có thể hay để chứng minh khái niệm này, càng nhiều thì càng tốt.
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;
}
};
Tôi hi vọng cái này giúp được!