Das letzte constbedeutet, dass die Funktion Method3die nicht veränderlichen Mitglieder ihrer Klasse nicht ändert.
const int* constbedeutet einen konstanten Zeiger auf eine Konstante int: dh einen Zeiger, der nicht geändert werden kann, auf einen int, der nicht geändert werden kann: Der einzige Unterschied zwischen dieser und der const int&besteht darin, dass dies möglich istnull
const int* const&bedeutet eine Referenz auf einen konstanten Zeiger auf eine Konstante int. Normalerweise werden Zeiger nicht als Referenz übergeben. const int* &Dies ist sinnvoller, da dies bedeuten würde, dass der Zeiger während des Methodenaufrufs geändert werden könnte. Dies ist der einzige Grund, warum ich sehe, dass ein Zeiger als Referenz übergeben const int* const&wird. Dies ist in jeder Hinsicht dasselbe, const int* constaußer dass er wahrscheinlich weniger effizient ist Da Zeiger einfache POD-Typen (Old Data) sind, sollten diese im Allgemeinen als Wert übergeben werden.
# 5 besagt, dass die gesamte Funktionsdeklaration links ist const, was impliziert, dass dies notwendigerweise eine Mitgliedsfunktion und keine freie Funktion ist.
# 4 besagt, dass der Zeiger links ist const(darf nicht geändert werden, um auf eine andere Adresse zu zeigen).
# 3 besagt, dass das intlinks ist const(darf nicht geändert werden, um einen anderen Wert zu haben).
# 2 sagt, dass der Zeiger nach links ist const.
# 1 sagt, dass das intauf der linken Seite ist const.
Wenn Sie alles zusammenfassen, können Sie dies als eine constMitgliedsfunktion mit dem Namen lesen Method3, die einen Verweis auf einen constZeiger auf ein int const(oder ein const int, wenn Sie es vorziehen) verwendet und einen constZeiger auf ein int const( const int) zurückgibt .
const int* constist daher gleichbedeutend mit int const * const.
constVersuchen Sie beim Lesen von Ausdrücken mit vielen Token und Zeigern immer, sie von rechts nach links zu lesen (nachdem Sie die obige Transformation angewendet haben). In diesem Fall ist der Rückgabewert ein const-Zeiger auf eine constint . Das constErstellen des Zeigers selbst macht hier keinen Sinn, da der Rückgabewert kein Wert ist, der geändert werden könnte. Durch das Erstellen des Pointees constwird jedoch garantiert, dass der Aufrufer das von zurückgegebene int(oder Array von ints) nicht ändern darf Method3.
const int*const&wird int const*const&, so ist es eine Referenz auf einen const Zeiger auf eine constint . Das Übergeben eines const-Zeigers durch männliche Referenzen macht ebenfalls keinen Sinn - Sie können den referenzierten Wert nicht ändern, da der Zeiger ist constund Referenzen und Zeiger den gleichen Speicherplatz belegen, sodass auch keine Platzersparnis entsteht.
Der letzte constgibt an, dass die Methode das thisObjekt nicht ändert . Der thisZeiger innerhalb des Methodenkörpers hat die (theoretische) Deklaration T const * const this. Dies bedeutet, dass ein const T*Objekt aufrufen kann T::Method3().
Stimmen Sie dies (und die ähnliche Antwort von ildjarn) ab, teilweise um darauf hinzuweisen, dass das Ganze sinnvoller ist, wenn Sie nicht das erste consts an die Spitze der Phrase setzen. Dies ist genau der Grund, warum ich denke, dass es eine schlechte Praxis ist, sie constdort zu platzieren, obwohl die Sprache dies zulässt und es die häufigste Verwendung ist.
TED
12
Eine einfache Möglichkeit, sich an die Regeln von zu erinnern, constbesteht darin, folgendermaßen darüber nachzudenken: constGilt für das Ding auf der linken Seite, es sei denn, es befindet sich nichts auf der linken Seite.
Im Fall von const int * consthat die erste Konstante nichts auf der linken Seite, also gilt sie für intund die zweite hat etwas auf der linken Seite, also gilt sie für den Zeiger.
Diese Regel sagt Ihnen auch, was in dem Fall passieren würde, in dem Sie haben const int const *. Da beide Konstanten für intdiesen Ausdruck gelten, ist er redundant und daher ungültig.
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 */
Ich verwende gerne die "Clock" - oder "Spiral" -Methode, bei der Sie ausgehend vom Bezeichnernamen (in diesem Fall Method3) von links nach rechts, von links nach links usw. hin und her lesen, um zu dekodieren Regeln der Namensgebung. Dies const int* const Method3(const int* const&) constgilt auch für eine Klassenmethode, die keine Klassenmitglieder (einer nicht benannten Klasse) ändert und einen konstanten Verweis auf einen Zeiger verwendet, der auf eine Konstante zeigt intund einen konstanten Zeiger auf eine Konstante zurückgibt int.
Eine einfache Möglichkeit, sich an die Konstante in C ++ zu erinnern, besteht darin, Code in folgender Form zu sehen:
XXX const;const YYY;
XXX, JJJ wird eine konstante Komponente sein, XXX constForm:
function ( def var )const;------#1*const;------#2
const YYY bilden:
constint;------#3constdouble;
Leute benutzen normalerweise diese Typen. Wenn Sie "const&"irgendwo sehen, fühlen Sie sich nicht verwirrt, const beschreibt etwas vor sich. Die Antwort auf dieses Problem liegt nun auf der Hand.
Ich möchte nur erwähnen, dass dies const int* const&in der Tat ein ständiger Hinweis ist const int*. Beispielsweise:
int i =0;int j =1;int* p =&i;int* q =&j;constint*const& cpref = p;
cpref = q;//Error: assignment of read-only reference 'cpref'
Es ist auch der Fall für int* const&, was bedeutet: "Ein ständiger Verweis auf int*".
Ist const int*&aber ein nicht konstanter Verweis auf const int*.
Hoffe das hilft.
Das Lesen von rechts nach links erleichtert das Verständnis von Modifikatoren.
Eine const-Methode, die einen Verweis auf einen const-Zeiger auf eine aufgerufene const int verwendet, Method3die einen const-Zeiger auf eine const int zurückgibt.
Eine const-Methode kann keine Mitglieder ändern (es sei denn, sie sind explizit
mutable)
Ein const-Zeiger kann nicht geändert werden, um auf etwas anderes zu verweisen
Ein const int (oder ein anderer Typ) kann nicht geändert werden
const # 1: Der von Methode3 zurückgegebene Zeiger verweist auf eine const int.
const # 2: Der von der Funktion selbst zurückgegebene Zeigerwert ist const. Dies ist eine nutzlose Konstante (obwohl grammatisch gültig), da der Rückgabewert einer Funktion kein l-Wert sein kann.
const # 3: Der Zeigertyp, der als Referenz auf die Funktion übergeben wird, zeigt auf eine const int.
const # 4: Der Zeigerwert, der als Verweis auf die Funktion übergeben wird, ist selbst ein const-Zeiger. Das Deklarieren eines Werts, der an eine Funktion als const übergeben wird, ist normalerweise sinnlos, aber dieser Wert wird als Referenz übergeben, sodass er sinnvoll sein kann.
const # 5: Die Funktion (vermutlich eine Mitgliedsfunktion) ist const, was bedeutet, dass es nicht erlaubt ist, (a) Mitgliedern des Objekts, zu dem sie gehört, neue Werte zuzuweisen oder (b) eine Nicht-const-Mitgliedsfunktion aufzurufen auf dem Objekt oder einem seiner Mitglieder.
const Am Ende der Methode befindet sich das Qualifikationsmerkmal, das angibt, dass der Status des Objekts nicht geändert wird.
const int*const&bedeutet, dass durch Verweisen ein const-Zeiger auf eine const-Position empfangen wird. Es kann weder geändert werden, um auf eine andere Position zu zeigen, noch den Wert ändern, auf den es zeigt.
const int*const ist der Rückgabewert, der auch ein konstanter Zeiger auf eine konstante Position ist.
Ein paar Beispiele könnten nett sein, um dieses Konzept zu demonstrieren, je mehr desto besser imho.
classTestClass{private:int iValue;int* oValuePtr;int& oValueRef;public:intTestClass::ByValMethod1(intValue){// Value can be modifiedValue++;// iValue can be modified
iValue =Value;
iValue +=1;// Return value can be modifiedreturn++iValue;}intTestClass::ByValMethod2(constintValue){// Value *cannot* be modified// Variable is const variableValue++;// iValue can be modified
iValue =Value;
iValue +=1;// Return value can be modifiedreturn++iValue;}constintTestClass::ByValMethod3(intValue){// Value can be modifiedValue++;// iValue can be modified
iValue =Value;
iValue +=1;// Return value can be modifiedreturn++iValue;}constintTestClass::ByValMethod4(constintValue){// Value *cannot* be modified// Variable is const variableValue++;// iValue can be modified
iValue =Value;
iValue +=1;// Return value can be modifiedreturn++iValue;}constintTestClass::ByValMethod5(constintValue)const{// Value *cannot* be modified// Variable is const variableValue++;// iValue *cannot* be modified// Access through a const object
iValue =Value;
iValue +=1;// Return value *cannot* be modified// Access through a const objectreturn++iValue;}int&TestClass::ByRefMethod1(int&Value){// Value can be modifiedValue++;// oValueRef can be modified
oValueRef =Value;
oValueRef +=1;// Return value can be modifiedreturn++oValueRef;}int&TestClass::ByRefMethod2(constint&Value){// Value *cannot* be modified// Variable is const variableValue++;// oValueRef can be modified
oValueRef =Value;
oValueRef +=1;// Return value can be modifiedreturn++oValueRef;}constint&TestClass::ByRefMethod3(int&Value){// Value can be modifiedValue++;// oValueRef can be modified
oValueRef =Value;
oValueRef +=1;// Return value can be modifiedreturn++oValueRef;}constint&TestClass::ByRefMethod4(constint&Value){// Value *cannot* be modified// Variable is const variableValue++;// oValueRef can be modified
oValueRef =Value;
oValueRef +=1;// Return value can be modifiedreturn++oValueRef;}constint&TestClass::ByRefMethod5(constint&Value)const{// Value *cannot* be modified// Variable is const variableValue++;// oValueRef can be modified
oValueRef =Value;
oValueRef +=1;// Return value can be modifiedreturn++oValueRef;}int*TestClass::PointerMethod1(int*Value){// Value can be modifiedValue++;// oValuePtr can be assigned
oValuePtr =Value;// oValuePtr can be modified
oValuePtr +=1;// Return value can be modifiedreturn++oValuePtr;}int*TestClass::PointerMethod2(constint*Value){// Value can be modifiedValue++;// oValuePtr cannot be assigned// const int* to int*
oValuePtr =Value;// oValuePtr can be modified
oValuePtr +=1;// Return value can be modifiedreturn++oValuePtr;}constint*TestClass::PointerMethod3(int*Value){// Value can be modifiedValue++;// oValuePtr can be assigned
oValuePtr =Value;// iValue can be modified
oValuePtr +=1;// Return value can be modifiedreturn++oValuePtr;}constint*TestClass::PointerMethod4(constint*Value){// Value cannot be modifiedValue++;// oValuePtr *cannot* be assigned// const int* to int*
oValuePtr =Value;// oValuePtr can be modified
oValuePtr +=1;// Return value can be modifiedreturn++oValuePtr;}constint*TestClass::PointerMethod5(constint*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 modifiedreturn++oValuePtr;}};
Antworten:
Lesen Sie dies: https://isocpp.org/wiki/faq/const-correctness
Das letzte
const
bedeutet, dass die FunktionMethod3
die nicht veränderlichen Mitglieder ihrer Klasse nicht ändert.const int* const
bedeutet einen konstanten Zeiger auf eine Konstante int: dh einen Zeiger, der nicht geändert werden kann, auf einen int, der nicht geändert werden kann: Der einzige Unterschied zwischen dieser und derconst int&
besteht darin, dass dies möglich istnull
const int* const&
bedeutet eine Referenz auf einen konstanten Zeiger auf eine Konstante int. Normalerweise werden Zeiger nicht als Referenz übergeben.const int* &
Dies ist sinnvoller, da dies bedeuten würde, dass der Zeiger während des Methodenaufrufs geändert werden könnte. Dies ist der einzige Grund, warum ich sehe, dass ein Zeiger als Referenz übergebenconst int* const&
wird. Dies ist in jeder Hinsicht dasselbe,const int* const
außer dass er wahrscheinlich weniger effizient ist Da Zeiger einfache POD-Typen (Old Data) sind, sollten diese im Allgemeinen als Wert übergeben werden.quelle
Es ist einfacher zu verstehen, wenn Sie dies als das völlig Äquivalent umschreiben
dann lies es von rechts nach links.
# 5 besagt, dass die gesamte Funktionsdeklaration links ist
const
, was impliziert, dass dies notwendigerweise eine Mitgliedsfunktion und keine freie Funktion ist.# 4 besagt, dass der Zeiger links ist
const
(darf nicht geändert werden, um auf eine andere Adresse zu zeigen).# 3 besagt, dass das
int
links istconst
(darf nicht geändert werden, um einen anderen Wert zu haben).# 2 sagt, dass der Zeiger nach links ist
const
.# 1 sagt, dass das
int
auf der linken Seite istconst
.Wenn Sie alles zusammenfassen, können Sie dies als eine
const
Mitgliedsfunktion mit dem Namen lesenMethod3
, die einen Verweis auf einenconst
Zeiger auf einint const
(oder einconst int
, wenn Sie es vorziehen) verwendet und einenconst
Zeiger auf einint const
(const int
) zurückgibt .(Nb # 2 ist völlig überflüssig .)
quelle
Erstens
const T
ist gleichbedeutend mitT const
.const int* const
ist daher gleichbedeutend mitint const * const
.const
Versuchen Sie beim Lesen von Ausdrücken mit vielen Token und Zeigern immer, sie von rechts nach links zu lesen (nachdem Sie die obige Transformation angewendet haben). In diesem Fall ist der Rückgabewert ein const-Zeiger auf eine constint
. Dasconst
Erstellen des Zeigers selbst macht hier keinen Sinn, da der Rückgabewert kein Wert ist, der geändert werden könnte. Durch das Erstellen des Pointeesconst
wird jedoch garantiert, dass der Aufrufer das von zurückgegebeneint
(oder Array vonint
s) nicht ändern darfMethod3
.const int*const&
wirdint const*const&
, so ist es eine Referenz auf einen const Zeiger auf eine constint
. Das Übergeben eines const-Zeigers durch männliche Referenzen macht ebenfalls keinen Sinn - Sie können den referenzierten Wert nicht ändern, da der Zeiger istconst
und Referenzen und Zeiger den gleichen Speicherplatz belegen, sodass auch keine Platzersparnis entsteht.Der letzte
const
gibt an, dass die Methode dasthis
Objekt nicht ändert . Derthis
Zeiger innerhalb des Methodenkörpers hat die (theoretische) DeklarationT const * const this
. Dies bedeutet, dass einconst T*
Objekt aufrufen kannT::Method3()
.quelle
const
s an die Spitze der Phrase setzen. Dies ist genau der Grund, warum ich denke, dass es eine schlechte Praxis ist, sieconst
dort zu platzieren, obwohl die Sprache dies zulässt und es die häufigste Verwendung ist.Eine einfache Möglichkeit, sich an die Regeln von zu erinnern,
const
besteht darin, folgendermaßen darüber nachzudenken:const
Gilt für das Ding auf der linken Seite, es sei denn, es befindet sich nichts auf der linken Seite.Im Fall von
const int * const
hat die erste Konstante nichts auf der linken Seite, also gilt sie fürint
und die zweite hat etwas auf der linken Seite, also gilt sie für den Zeiger.Diese Regel sagt Ihnen auch, was in dem Fall passieren würde, in dem Sie haben
const int const *
. Da beide Konstanten fürint
diesen Ausdruck gelten, ist er redundant und daher ungültig.quelle
quelle
Ich verwende gerne die "Clock" - oder "Spiral" -Methode, bei der Sie ausgehend vom Bezeichnernamen (in diesem Fall
Method3
) von links nach rechts, von links nach links usw. hin und her lesen, um zu dekodieren Regeln der Namensgebung. Diesconst int* const Method3(const int* const&) const
gilt auch für eine Klassenmethode, die keine Klassenmitglieder (einer nicht benannten Klasse) ändert und einen konstanten Verweis auf einen Zeiger verwendet, der auf eine Konstante zeigtint
und einen konstanten Zeiger auf eine Konstante zurückgibtint
.Hoffe das hilft,
Jason
quelle
Eine einfache Möglichkeit, sich an die Konstante in C ++ zu erinnern, besteht darin, Code in folgender Form zu sehen:
XXX, JJJ wird eine konstante Komponente sein,
XXX const
Form:const YYY
bilden:Leute benutzen normalerweise diese Typen. Wenn Sie
"const&"
irgendwo sehen, fühlen Sie sich nicht verwirrt, const beschreibt etwas vor sich. Die Antwort auf dieses Problem liegt nun auf der Hand.quelle
Ich möchte nur erwähnen, dass dies
const int* const&
in der Tat ein ständiger Hinweis istconst int*
. Beispielsweise:Es ist auch der Fall für
int* const&
, was bedeutet: "Ein ständiger Verweis aufint*
".Ist
const int*&
aber ein nicht konstanter Verweis aufconst int*
.Hoffe das hilft.
quelle
Das Lesen von rechts nach links erleichtert das Verständnis von Modifikatoren.
Eine const-Methode, die einen Verweis auf einen const-Zeiger auf eine aufgerufene const int verwendet,
Method3
die einen const-Zeiger auf eine const int zurückgibt.mutable
)quelle
const # 1: Der von Methode3 zurückgegebene Zeiger verweist auf eine const int.
const # 2: Der von der Funktion selbst zurückgegebene Zeigerwert ist const. Dies ist eine nutzlose Konstante (obwohl grammatisch gültig), da der Rückgabewert einer Funktion kein l-Wert sein kann.
const # 3: Der Zeigertyp, der als Referenz auf die Funktion übergeben wird, zeigt auf eine const int.
const # 4: Der Zeigerwert, der als Verweis auf die Funktion übergeben wird, ist selbst ein const-Zeiger. Das Deklarieren eines Werts, der an eine Funktion als const übergeben wird, ist normalerweise sinnlos, aber dieser Wert wird als Referenz übergeben, sodass er sinnvoll sein kann.
const # 5: Die Funktion (vermutlich eine Mitgliedsfunktion) ist const, was bedeutet, dass es nicht erlaubt ist, (a) Mitgliedern des Objekts, zu dem sie gehört, neue Werte zuzuweisen oder (b) eine Nicht-const-Mitgliedsfunktion aufzurufen auf dem Objekt oder einem seiner Mitglieder.
quelle
const
Am Ende der Methode befindet sich das Qualifikationsmerkmal, das angibt, dass der Status des Objekts nicht geändert wird.const int*const&
bedeutet, dass durch Verweisen ein const-Zeiger auf eine const-Position empfangen wird. Es kann weder geändert werden, um auf eine andere Position zu zeigen, noch den Wert ändern, auf den es zeigt.const int*const
ist der Rückgabewert, der auch ein konstanter Zeiger auf eine konstante Position ist.quelle
Ein paar Beispiele könnten nett sein, um dieses Konzept zu demonstrieren, je mehr desto besser imho.
Ich hoffe das hilft!
quelle