回答:
これを読んでください:https : //isocpp.org/wiki/faq/const-correctness
最後const
は、関数Method3
がそのクラスの変更不可能なメンバーを変更しないことを意味します。
const int* const
は、定数intへの定数ポインタを意味します。つまり、変更できないポインタ、変更できないintへのポインタです。これとの唯一の違いconst int&
は、null
const int* const&
定数intへの定数ポインタへの参照を意味します。通常、ポインターは参照渡しされません。const int* &
メソッドの呼び出し中にポインターが変更される可能性があることを意味するので、より意味があります。これは、ポインターを参照で渡すことを確認できる唯一の理由ですconst int* const&
が、すべての意図と目的が、const int* const
おそらく効率が悪いことを除いて同じです。ポインタはプレーンオールドデータ(POD)タイプであり、これらは一般に値で渡される必要があるためです。
それを完全に同等のものとして書き直すと理解しやすくなります
// 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;
次に、右から左に読んでください。
#5は、左側の関数宣言全体がconst
であることを示しています。これは、これがフリー関数ではなくメンバー関数であることを意味します。
#4は、左へのポインタがconst
(別のアドレスを指すように変更されない場合がある)であることを示しています。
#3はint
、左側がであるconst
ことを示しています(別の値に変更することはできません)。
#2は、左へのポインタがであることを示していますconst
。
#1はint
、左側がであることを示していconst
ます。
すべて一緒にそれを置く、あなたはこれを読むことができるconst
という名前のメンバ関数Method3
への参照取りconst
へのポインタint const
(またはconst int
あなたが好む場合、)とを返すconst
へのポインタをint const
(const int
)。
(Nb#2 は完全に不要です。)
まず、const T
と同等T const
です。
const int* const
したがって、はと同等int const * const
です。
多数のconst
トークンとポインタが含まれる式を読み取る場合は、常に上記の変換を適用した後、右から左に読み取ってみてください。したがって、この場合、戻り値はconstへのconstポインタint
です。const
戻り値は変更できる左辺値ではないため、ここではポインタ自体を作成しても意味がありません。const
ただし、指示先を作成すると、呼び出し元がによって返されたint
(またはの配列int
)を変更できないことが保証されMethod3
ます。
const int*const&
になるint const*const&
ので、これはconstへのconstポインタへの参照int
です。参照によるconstポインターの受け渡しも意味がありません-参照された値を変更することはできません。これは、ポインターがconst
同じであり、参照とポインターが等しいストレージを占有するため、スペースを節約することもできないためです。
最後const
は、メソッドがthis
オブジェクトを変更しないことを示しています。this
メソッド本体内のポインターには、(理論的な)宣言がありT const * const this
ます。つまり、const T*
オブジェクトはを呼び出すことができますT::Method3()
。
const
のsをフレーズの先頭に置かない方が全体的に意味があるということを部分的に指摘するためです。const
言語がそれを許すとしても、そこに置くことは悪い習慣だと私が思う理由はまさにこれであり、それは最も一般的な使用法です。
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 */
私は「クロック」または「スパイラル」メソッドを使用するのが好きです。ここでは、識別子名(この場合はMethod3
)から始めて、左から右、左から右などに前後に読み取ってデコードします。命名規則。だから、const int* const Method3(const int* const&) const
(いくつかの非名前のクラスの)任意のクラスのメンバーを変更しないクラスメソッドであり、ポインタに一定の基準をとる定数を指しint
戻る定数に定数ポインタint
。
お役に立てれば、
ジェイソン
C ++でconstを覚える簡単な方法は、次のような形式のコードを表示することです。
XXX const;
const YYY;
XXX、YYYは定数コンポーネント、
XXX const
形式:
function ( def var ) const; ------#1
* const; ------#2
const YYY
形:
const int; ------#3
const double;
人々は通常これらのタイプを使用します。"const&"
どこかで見たとき、混乱しないでください。constは自分自身の前に何かを記述しています。したがって、この問題の答えは自明です。
const int* const Method3(const int* const&) const;
| | | | |
#3 #2 #3 #2 #1
それconst int* const&
は確かにへの一定の参照であることを述べたいだけですconst int*
。例えば:
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'
これはの場合にもint* const&
当てはまります。つまり、「への一定の参照int*
」です。
しかしconst int*&
、への非定数参照const int*
です。
お役に立てれば。
const#1:Method3によって返されるポインターはconst intを参照します。
const#2:関数自体が返すポインター値はconstです。関数からの戻り値をl値にすることはできないため、これは(文法的には有効ですが)役に立たないconstです。
const#3:関数への参照によって渡されるポインター型はconst intを指します。
const#4:関数への参照によって渡されるポインター値は、それ自体がconstポインターです。関数に渡される値をconstとして宣言しても通常は意味がありませんが、この値は参照によって渡されるため、意味がある場合があります。
const#5:関数(おそらくメンバー関数)はconstです。つまり、(a)新しい値を、それが属しているオブジェクトのメンバーに割り当てたり、(b)非constメンバー関数を呼び出したりすることはできません。オブジェクトまたはそのメンバーのいずれか。
いくつかの例がこの概念を実証するために良いかもしれません、より良い私見です。
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;
}
};
これが役に立てば幸いです!