Wie weit gehst du mit const
? Machst du nur Funktionen, const
wenn es nötig ist, oder gehst du das ganze Schwein und benutzt es überall? Stellen Sie sich zum Beispiel einen einfachen Mutator vor, der einen einzelnen booleschen Parameter akzeptiert:
void SetValue(const bool b) { my_val_ = b; }
Ist das const
eigentlich sinnvoll? Persönlich entscheide ich mich dafür, es ausgiebig zu nutzen, einschließlich der Parameter, aber in diesem Fall frage ich mich, ob es sich lohnt?
Ich war auch überrascht zu erfahren, dass Sie const
Parameter in einer Funktionsdeklaration weglassen können, diese aber in die Funktionsdefinition aufnehmen können, z.
.h Datei
void func(int n, long l);
CPP-Datei
void func(const int n, const long l)
Gibt es einen Grund dafür? Es scheint mir ein wenig ungewöhnlich.
Antworten:
Der Grund dafür ist, dass const für den Parameter nur lokal innerhalb der Funktion gilt, da er an einer Kopie der Daten arbeitet. Dies bedeutet, dass die Funktionssignatur sowieso wirklich dieselbe ist. Es ist wahrscheinlich ein schlechter Stil, dies viel zu tun.
Ich persönlich neige dazu, const nur für Referenz- und Zeigerparameter zu verwenden. Für kopierte Objekte spielt es keine Rolle, obwohl es sicherer sein kann, da es die Absicht innerhalb der Funktion signalisiert. Es ist wirklich ein Urteilsspruch. Ich neige jedoch dazu, const_iterator zu verwenden, wenn ich etwas schleife, und ich beabsichtige nicht, es zu ändern, also denke ich, dass jeder sein eigenes hat, solange die const-Korrektheit für Referenztypen streng eingehalten wird.
quelle
const
von Funktionsprototypen hat den Vorteil, dass Sie die Header-Datei nicht ändern müssen, wenn Sieconst
später aus dem Implementierungsteil löschen möchten.const
wo es einen nützlichen Unterschied macht."const
wann immer dies möglich ist. es ist ausdrucksvoller. Wenn ich den Code eines anderen lese, benutze ich kleine Indikatoren wie diesen, um zu beurteilen, wie viel Sorgfalt er beim Schreiben seines Codes neben Dingen wie magischen Zahlen, Kommentaren und der richtigen Verwendung von Zeigern usw. verwendet.int getDouble(int a){ ++a; return 2*a; }
Versuche dies. Natürlich hat das++a
dort nichts zu tun, aber es kann dort in einer langen Funktion gefunden werden, die von mehr als einem Programmierer über einen langen Zeitraum geschrieben wurde. Ich würde dringend empfehlen, zu schreiben,int getDouble( const int a ){ //... }
dass beim Finden ein Kompilierungsfehler auftritt++a;
.class Foo { int multiply(int a, int b) const; }
in Ihren Header. Bei Ihrer Implementierung ist es Ihnen wichtig, dass Sie versprechen, sich nicht zu ändern,a
undb
diesint Foo::multiply(const int a, const int b) const { }
ist hier sinnvoll. (Nebenbemerkung: Sowohl der Aufrufer als auch die Implementierung kümmern sich darum, dass die Funktion ihrFoo
Objekt nicht ändert , daher die Konstante am Ende ihrer Deklaration.)"const ist sinnlos, wenn das Argument als Wert übergeben wird, da Sie das Objekt des Aufrufers nicht ändern."
Falsch.
Es geht darum, Ihren Code und Ihre Annahmen selbst zu dokumentieren.
Wenn an Ihrem Code viele Leute arbeiten und Ihre Funktionen nicht trivial sind, sollten Sie alles markieren, was Sie können. Wenn Sie Code mit industrieller Stärke schreiben, sollten Sie immer davon ausgehen, dass Ihre Mitarbeiter Psychopathen sind, die versuchen, Sie auf jede erdenkliche Weise zu erreichen (zumal es in Zukunft oft Sie selbst sind).
Außerdem, wie jemand bereits erwähnt, es könnte die Compiler optimiert die Dinge ein wenig helfen (obwohl es eine lange gedreht ist).
quelle
Manchmal (zu oft!) Muss ich den C ++ - Code eines anderen entwirren. Und wir alle wissen, dass der C ++ - Code eines anderen fast per Definition ein komplettes Durcheinander ist :) Das erste, was ich mache, um den lokalen Datenfluss zu entschlüsseln, ist, const in jede Variablendefinition zu setzen, bis der Compiler anfängt zu bellen. Dies bedeutet auch const-qualifizierende Wertargumente, da es sich nur um ausgefallene lokale Variablen handelt, die vom Aufrufer initialisiert wurden.
Ah, ich wünschte, Variablen wären standardmäßig const und für Nicht-const-Variablen wäre veränderbar erforderlich :)
quelle
[x](){return ++x;}
ein Fehler. siehe hierconst
" standardmäßig in Rust :)Die folgenden zwei Zeilen sind funktional äquivalent:
Natürlich können Sie
a
den Körper nicht ändern,foo
wenn er auf die zweite Weise definiert ist, aber es gibt keinen Unterschied von außen.Was
const
wirklich nützlich ist, sind Referenz- oder Zeigerparameter:Dies besagt, dass foo einen großen Parameter annehmen kann, möglicherweise eine Datenstruktur mit einer Größe von Gigabyte, ohne ihn zu kopieren. Außerdem sagt es dem Aufrufer: "Foo wird den Inhalt dieses Parameters nicht ändern." Durch das Übergeben einer const-Referenz kann der Compiler auch bestimmte Leistungsentscheidungen treffen.
*: Es sei denn, es wirft die Konstanz weg, aber das ist ein anderer Beitrag.
quelle
Extra überflüssige Konstanten sind vom API-Standpunkt aus schlecht:
Wenn Sie in Ihren Code zusätzliche überflüssige Konstanten für vom Wert übergebene intrinsische Typparameter einfügen, wird Ihre API unübersichtlich, während dem Aufrufer oder API-Benutzer kein aussagekräftiges Versprechen gegeben wird (dies behindert nur die Implementierung).
Zu viele 'const' in einer API, wenn sie nicht benötigt werden, sind wie " weinender Wolf ". Irgendwann werden die Leute anfangen, 'const' zu ignorieren, weil es überall ist und die meiste Zeit nichts bedeutet.
Das Argument "reductio ad absurdum" für zusätzliche Konstanten in der API ist gut für diese ersten beiden Punkte. Wenn mehr Konstantenparameter gut sind, sollte jedes Argument, das eine Konstante enthalten kann, eine Konstante enthalten. Wenn es wirklich so gut wäre, möchten Sie, dass const die Standardeinstellung für Parameter ist und nur dann ein Schlüsselwort wie "veränderlich" hat, wenn Sie den Parameter ändern möchten.
Versuchen wir also, const einzufügen, wo immer wir können:
Betrachten Sie die obige Codezeile. Die Deklaration ist nicht nur übersichtlicher und länger und schwerer zu lesen, sondern drei der vier 'const'-Schlüsselwörter können vom API-Benutzer sicher ignoriert werden. Die zusätzliche Verwendung von 'const' hat die zweite Zeile jedoch möglicherweise GEFÄHRLICH gemacht!
Warum?
Eine schnelle Fehlinterpretation des ersten Parameters
char * const buffer
könnte den Eindruck erwecken, dass der übergebene Speicher im Datenpuffer nicht geändert wird. Dies ist jedoch nicht der Fall! Überflüssiges 'const' kann zu gefährlichen und falschen Annahmen über Ihre API führen, wenn es schnell gescannt oder falsch gelesen wird.Überflüssige Konstanten sind auch vom Standpunkt der Code-Implementierung aus schlecht:
Wenn FLEXIBLE_IMPLEMENTATION nicht wahr ist, verspricht die API, die Funktion nicht wie folgt zu implementieren.
Das ist ein sehr dummes Versprechen. Warum sollten Sie ein Versprechen abgeben, das Ihrem Anrufer überhaupt keinen Nutzen bringt und nur Ihre Implementierung einschränkt?
Beide sind absolut gültige Implementierungen derselben Funktion, sodass Sie nur unnötig eine Hand hinter den Rücken gebunden haben.
Darüber hinaus ist es ein sehr flaches Versprechen, das leicht (und rechtlich umgangen) werden kann.
Schauen Sie, ich habe es trotzdem so implementiert, obwohl ich versprochen habe, es nicht zu tun - nur mit einer Wrapper-Funktion. Es ist wie wenn der Böse verspricht, jemanden in einem Film nicht zu töten und seinem Handlanger befiehlt, ihn stattdessen zu töten.
Diese überflüssigen Konstanten sind nicht mehr wert als ein Versprechen eines Filmbösewichts.
Aber die Fähigkeit zu lügen wird noch schlimmer:
Ich wurde aufgeklärt, dass Sie const in Header (Deklaration) und Code (Definition) nicht übereinstimmen können, indem Sie falsche const verwenden. Die const-happy-Befürworter behaupten, dies sei eine gute Sache, da Sie const nur in die Definition einfügen können.
Das Gegenteil ist jedoch der Fall ... Sie können eine falsche Konstante nur in die Deklaration einfügen und in der Definition ignorieren. Dies macht überflüssige Konstanten in einer API nur zu einer schrecklichen Sache und einer schrecklichen Lüge - siehe dieses Beispiel:
Alles, was die überflüssige Konstante tatsächlich tut, ist, den Code des Implementierers weniger lesbar zu machen, indem er gezwungen wird, eine andere lokale Kopie oder eine Wrapper-Funktion zu verwenden, wenn er die Variable ändern oder die Variable als Nicht-Konstanten-Referenz übergeben möchte.
Schauen Sie sich dieses Beispiel an. Welches ist besser lesbar? Ist es offensichtlich, dass der einzige Grund für die zusätzliche Variable in der zweiten Funktion darin besteht, dass ein API-Designer eine überflüssige Konstante eingegeben hat?
Hoffentlich haben wir hier etwas gelernt. Überflüssige Konstante ist ein API-überfüllter Schandfleck, ein nerviger Nörgler, ein flaches und bedeutungsloses Versprechen, ein unnötiges Hindernis und führt gelegentlich zu sehr gefährlichen Fehlern.
quelle
void foo(int)
und hatvoid foo(const int)
genau die gleiche Funktion, keine Überlastungen. ideone.com/npN4W4 ideone.com/tZav9R Die Konstante hier ist nur ein Implementierungsdetail des Funktionskörpers und hat keinen Einfluss auf die Überlastungsauflösung. Lassen Sie const für eine sicherere und übersichtlichere API aus der Deklaration heraus, fügen Sie jedoch const in die Definition ein , wenn Sie den kopierten Wert nicht ändern möchten .pi++
wenn sie es nicht sollen.const sollte die Standardeinstellung in C ++ sein. So was :
quelle
unsigned
sollte die Standardeinstellung in C ++ gewesen sein. So:int i = 5; // i is unsigned
undsigned int i = 5; // i is signed
.Als ich C ++ für meinen Lebensunterhalt codierte, habe ich alles festgelegt, was ich konnte. Die Verwendung von const ist eine großartige Möglichkeit, dem Compiler zu helfen, Ihnen zu helfen. Wenn Sie beispielsweise die Rückgabewerte Ihrer Methode festlegen, können Sie Tippfehler wie Folgendes vermeiden:
als du meintest:
Wenn foo () definiert ist, um eine nicht konstante Referenz zurückzugeben:
Der Compiler lässt Sie gerne dem vom Funktionsaufruf zurückgegebenen anonymen temporären Wert einen Wert zuweisen. Making it const:
Beseitigt diese Möglichkeit.
quelle
foo() = 42
: Fehler: lWert als linker Operand der Zuweisung erforderlichconst int foo()
ist von einem anderen Typ alsint foo()
, was Sie in große Schwierigkeiten bringt, wenn Sie Dinge wie Funktionszeiger, Signal- / Slot-Systeme oder boost :: bind verwenden.const int& foo()
effektiv dasselbe wieint foo()
aufgrund der Rückgabewertoptimierung?Es gibt eine gute Diskussion zu diesem Thema in den alten "Guru der Woche" -Artikeln auf comp.lang.c ++., Die hier moderiert werden .
Der entsprechende GOTW Artikel ist auf Herb Sutter-Website verfügbar hier .
quelle
Ich sage const Ihre Wertparameter.
Betrachten Sie diese Buggy-Funktion:
Wenn der Parameter number const wäre, würde der Compiler anhalten und uns vor dem Fehler warnen.
quelle
Ich verwende const für Funktionsparameter, die Referenzen (oder Zeiger) sind, die nur [in] Daten sind und von der Funktion nicht geändert werden. Das heißt, wenn der Zweck der Verwendung einer Referenz darin besteht, das Kopieren von Daten zu vermeiden und das Ändern des übergebenen Parameters nicht zuzulassen.
Wenn Sie in Ihrem Beispiel const auf den booleschen b-Parameter setzen, wird die Implementierung nur eingeschränkt und es wird kein Beitrag zur Schnittstelle der Klasse geleistet (obwohl normalerweise empfohlen wird, die Parameter nicht zu ändern).
Die Funktionssignatur für
und
ist das gleiche, was Ihre .c und .h erklärt
Asaf
quelle
Wenn Sie die Operatoren
->*
oder verwenden.*
, ist dies ein Muss.Es hindert Sie daran, so etwas zu schreiben
was ich jetzt fast getan habe und was wahrscheinlich nicht das tut, was Sie beabsichtigen.
Was ich sagen wollte war
und wenn ich ein
const
dazwischen gesetzt hätteBar *
undp
, hätte mir der Compiler das gesagt.quelle
Ah, eine schwierige Frage. Auf der einen Seite ist eine Deklaration ein Vertrag und es ist wirklich nicht sinnvoll, ein const-Argument als Wert zu übergeben. Wenn Sie sich andererseits die Funktionsimplementierung ansehen, geben Sie dem Compiler mehr Möglichkeiten zur Optimierung, wenn Sie eine Argumentkonstante deklarieren.
quelle
const ist sinnlos, wenn das Argument als Wert übergeben wird, da Sie das Objekt des Aufrufers nicht ändern.
const sollte beim Übergeben als Referenz bevorzugt werden, es sei denn, der Zweck der Funktion besteht darin, den übergebenen Wert zu ändern.
Schließlich kann und sollte eine Funktion, die das aktuelle Objekt (dies) nicht ändert, als const deklariert werden. Ein Beispiel ist unten:
Dies ist ein Versprechen, das Objekt, auf das dieser Aufruf angewendet wird, nicht zu ändern. Mit anderen Worten, Sie können anrufen:
Wenn die Funktion nicht const wäre, würde dies zu einer Compiler-Warnung führen.
quelle
Das Markieren von Wertparametern 'const' ist definitiv eine subjektive Sache.
Allerdings ziehe ich es tatsächlich vor, Werteparameter const zu markieren, genau wie in Ihrem Beispiel.
Der Wert zeigt für mich deutlich an, dass die Funktionsparameterwerte von der Funktion niemals geändert werden. Sie haben am Anfang den gleichen Wert wie am Ende. Für mich gehört es dazu, einen sehr funktionalen Programmierstil beizubehalten.
Für eine kurze Funktion ist es wohl eine Verschwendung von Zeit / Raum, die 'const' dort zu haben, da es normalerweise ziemlich offensichtlich ist, dass die Argumente nicht von der Funktion geändert werden.
Bei einer größeren Funktion handelt es sich jedoch um eine Form der Implementierungsdokumentation, die vom Compiler erzwungen wird.
Ich kann sicher sein, dass ich, wenn ich mit 'n' und 'l' rechne, diese Berechnung umgestalten / verschieben kann, ohne befürchten zu müssen, dass ein anderes Ergebnis erzielt wird, da ich einen Ort verpasst habe, an dem einer oder beide geändert wurden.
Da es sich um ein Implementierungsdetail handelt, müssen Sie die Werteparameter const im Header nicht deklarieren, genauso wie Sie die Funktionsparameter nicht mit denselben Namen deklarieren müssen, die die Implementierung verwendet.
quelle
Möglicherweise ist dies kein gültiges Argument. Wenn wir jedoch den Wert einer const-Variablen in einem Funktionscompiler erhöhen, erhalten wir einen Fehler: " Fehler: Inkrement des schreibgeschützten Parameters ". Das bedeutet, dass wir das Schlüsselwort const verwenden können, um zu verhindern, dass unsere Variablen innerhalb von Funktionen versehentlich geändert werden (was nicht / schreibgeschützt sein soll). Wenn wir es also versehentlich zur Kompilierungszeit gemacht haben, wird uns der Compiler dies mitteilen. Dies ist besonders wichtig, wenn Sie nicht der einzige sind, der an diesem Projekt arbeitet.
quelle
Ich neige dazu, const zu verwenden, wo immer dies möglich ist. (Oder ein anderes geeignetes Schlüsselwort für die Zielsprache.) Ich mache dies nur, weil es dem Compiler ermöglicht, zusätzliche Optimierungen vorzunehmen, die er sonst nicht vornehmen könnte. Da ich keine Ahnung habe, wie diese Optimierungen aussehen könnten, mache ich es immer, auch wenn es albern erscheint.
Nach allem, was ich weiß, sieht der Compiler möglicherweise einen Parameter für den konstanten Wert und sagt: "Hey, diese Funktion ändert ihn sowieso nicht, sodass ich als Referenz übergeben und einige Taktzyklen speichern kann." Ich glaube nicht, dass es jemals so etwas tun würde, da es die Funktionssignatur ändert, aber es macht den Punkt. Vielleicht macht es eine andere Stack-Manipulation oder so ... Der Punkt ist, ich weiß es nicht, aber ich weiß, dass der Versuch, schlauer zu sein als der Compiler, nur dazu führt, dass ich beschämt werde.
C ++ hat etwas mehr Gepäck, mit der Idee der Konstantenkorrektheit, so dass es noch wichtiger wird.
quelle
const
. Es geht vielmehr darum, die Absicht innerhalb der Implementierung anzugeben und später Thinkoes zu fangen (versehentlich die falsche lokale Variable zu erhöhen, weil dies nicht der Fall warconst
). Parallel dazu möchte ich hinzufügen, dass Compiler sehr willkommen sind, Funktionssignaturen in dem Sinne zu ändern, dass Funktionen inline eingefügt werden können und einmal inline die gesamte Funktionsweise geändert werden kann. Das Hinzufügen oder Entfernen von Referenzen, das Erstellen von 'Variablen'-Literalen usw. gehören1. Beste Antwort basierend auf meiner Einschätzung:
Die Antwort von @Adisak ist nach meiner Einschätzung die beste Antwort hier. Beachten Sie, dass diese Antwort zum Teil die beste ist, da sie neben der Verwendung von Sound und durchdachter Logik auch die am besten abgesicherte mit echten Codebeispielen ist.
2. Meine eigenen Worte (in Übereinstimmung mit der besten Antwort):
const
. Alles was es tut ist:const
überall dies behindern kann.const
unnötige Überladen des Codes mitconst
s überall, wodurch die Aufmerksamkeit von denconst
s abgelenkt wird , die wirklich notwendig sind, um sicheren Code zu haben.const
ist von entscheidenden Bedeutung , wenn nötig, und muss verwendet werden, da sie unerwünschte Nebenwirkungen im Zusammenhang mit persistenten Änderungen verhindern außerhalb der Funktion, und daher jeder einzelner Zeiger oder eine Referenz muss verwenden ,const
wenn die Parm nur ein Eingang, keine Ausgabe. Die Verwendungconst
nur von Parametern, die als Referenz oder Zeiger übergeben werden, hat den zusätzlichen Vorteil, dass deutlich wird, welche Parameter Zeiger oder Referenzen sind. Es ist noch eine Sache, herauszustechen und zu sagen: "Achtung! Jeder Parameterconst
daneben ist eine Referenz oder ein Zeiger!".3. Googles Worte (stimme mir zu und die beste Antwort):
(Aus dem " Google C ++ Style Guide ")
Quelle: Abschnitt "Verwendung von const" im Google C ++ - Style Guide: https://google.github.io/styleguide/cppguide.html#Use_of_const . Dies ist eigentlich ein wirklich wertvoller Abschnitt, lesen Sie also den gesamten Abschnitt.
Beachten Sie, dass "TotW # 109" für "Tipp der Woche # 109: Sinnvoll
const
in Funktionsdeklarationen" steht und auch eine nützliche Lektüre ist. Es ist informativer und weniger aussagekräftig, was zu tun ist, und basiert auf dem Kontext, der vor derconst
oben zitierten Google C ++ - Style Guide-Regel erstellt wurde. Aufgrund der Klarheit wurde die oben angegebeneconst
Regel jedoch zu Google C ++ hinzugefügt Gestaltungsrichtlinie.Beachten Sie auch, dass ich, obwohl ich hier zur Verteidigung meiner Position den Google C ++ - Style Guide zitiere, NICHT bedeutet, dass ich immer dem Guide folge oder immer empfehle, dem Guide zu folgen. Einige der Dinge, die sie empfehlen, sind einfach komisch, wie zum Beispiel ihre
kDaysInAWeek
Namenskonvention für "Konstante Namen" . Es ist jedoch immer noch nützlich und relevant, darauf hinzuweisen, wenn eines der erfolgreichsten und einflussreichsten technischen und Softwareunternehmen der Welt dieselbe Rechtfertigung verwendet wie ich und andere wie @Adisak, um unsere Standpunkte in dieser Angelegenheit zu untermauern.4. Clangs Linter
clang-tidy
hat einige Optionen dafür:A. Es ist auch erwähnenswert, dass Clang der Linter,
clang-tidy
hat eine Option,readability-avoid-const-params-in-decls
, hier beschrieben , zu unterstützen , in einer Code - Basis Durchsetzung nicht mitconst
für Pass-by-Value - Funktion Parameter :Und hier sind zwei weitere Beispiele, die ich der Vollständigkeit und Klarheit halber hinzufüge:
B. Es gibt auch folgende Option:
readability-const-return-type
- https://clang.llvm.org/extra/clang-tidy/checks/readability-const-return-type.html5. Mein pragmatischer Ansatz, wie ich einen Styleguide zu diesem Thema formulieren würde:
Ich würde dies einfach kopieren und in meinen Styleguide einfügen:
[KOPIEREN / EINFÜGEN STARTEN]
const
Funktion immer für Funktionsparameter, die als Referenz oder Zeiger übergeben werden, wenn deren Inhalt (auf den sie zeigen) NICHT geändert werden soll. Auf diese Weise wird deutlich, wann eine Variable, die als Referenz oder Zeiger übergeben wird, voraussichtlich geändert wird, da sie fehltconst
. In diesem Anwendungsfall werdenconst
versehentliche Nebenwirkungen außerhalb der Funktion verhindert.const
Funktionsparameter zu verwenden, die als Wert übergeben werden, da diesconst
keine Auswirkungen auf den Aufrufer hat: Selbst wenn die Variable in der Funktion geändert wird, treten außerhalb der Funktion keine Nebenwirkungen auf. Weitere Begründungen und Einblicke finden Sie in den folgenden Ressourcen:const
in Funktionserklärungen"const
[dh:const
für vom Wert übergebene Parameter] für Funktionsparameter in Deklarationen, die keine Definitionen sind (und achten Sie darauf, keine bedeutungslosen zu kopieren / einzufügenconst
). Es ist bedeutungslos und wird vom Compiler ignoriert, es ist visuelles Rauschen und es könnte die Leser irreführen "( https://abseil.io/tips/109 , Hervorhebung hinzugefügt).const
Qualifizierer, die sich auf die Kompilierung auswirken, sind diejenigen, die in der Funktionsdefinition platziert sind, NICHT diejenigen in einer Vorwärtsdeklaration der Funktion, wie z. B. in einer Funktions- (Methoden-) Deklaration in einer Header-Datei.const
[dh:const
von Variablen als Wert übergeben ] auf Werte zurück durch eine Funktion.const
von Zeigern oder Referenzen, die von einer Funktion zurückgegeben werden, liegt beim Implementierer , da dies manchmal nützlich ist.clang-tidy
Optionen mit den folgenden Optionen:Hier sind einige Codebeispiele, um die
const
oben beschriebenen Regeln zu demonstrieren :const
Parameterbeispiele:(einige sind hier ausgeliehen )
const
Beispiele für Rückgabetypen:(einige sind von hier ausgeliehen )
[COPY / PASTE END]
quelle
In dem von Ihnen erwähnten Fall hat dies keine Auswirkungen auf Aufrufer Ihrer API, weshalb dies normalerweise nicht erfolgt (und im Header nicht erforderlich ist). Dies betrifft nur die Implementierung Ihrer Funktion.
Es ist keine besonders schlechte Sache, aber die Vorteile sind nicht so groß, da sie sich nicht auf Ihre API auswirken und die Eingabe hinzufügen, sodass dies normalerweise nicht der Fall ist.
quelle
Ich verwende const nicht für wertübergebene Parameter. Dem Aufrufer ist es egal, ob Sie den Parameter ändern oder nicht, es handelt sich um ein Implementierungsdetail.
Was wirklich wichtig ist, ist, Methoden als const zu markieren, wenn sie ihre Instanz nicht ändern. Tun Sie dies, während Sie fortfahren, da Sie sonst entweder viel const_cast <> erhalten oder feststellen, dass zum Markieren einer Methode const viel Code geändert werden muss, da andere Methoden aufgerufen werden, die als const markiert werden sollten.
Ich neige auch dazu, lokale vars const zu markieren, wenn ich sie nicht ändern muss. Ich glaube, es erleichtert das Verständnis des Codes, indem es die "beweglichen Teile" leichter identifiziert.
quelle
Zu Compiler-Optimierungen: http://www.gotw.ca/gotw/081.htm
quelle
Ich benutze const wo ich kann. Konstante für Parameter bedeutet, dass sie ihren Wert nicht ändern sollten. Dies ist besonders wertvoll, wenn Sie als Referenz übergeben werden. const for function erklärt, dass die Funktion die Klassenmitglieder nicht ändern soll.
quelle
Zusammenfassen:
std::vector::at(size_type pos)
. Was für die Standardbibliothek gut genug ist, ist gut für mich.quelle
_Tmp
- das möchten Sie nicht (eigentlich dürfen Sie sie nicht verwenden).Wenn der Parameter als Wert übergeben wird (und keine Referenz ist), gibt es normalerweise keinen großen Unterschied, ob der Parameter als const deklariert ist oder nicht (es sei denn, er enthält ein Referenzelement - kein Problem für integrierte Typen). Wenn der Parameter eine Referenz oder ein Zeiger ist, ist es normalerweise besser, den referenzierten / referenzierten Speicher zu schützen, nicht den Zeiger selbst (ich denke, Sie können die Referenz selbst nicht konstant machen, nicht, dass es wichtig ist, da Sie den Schiedsrichter nicht ändern können). . Es scheint eine gute Idee zu sein, alles zu schützen, was Sie als Konstante können. Sie können es weglassen, ohne befürchten zu müssen, einen Fehler zu machen, wenn es sich bei den Parametern nur um PODs (einschließlich integrierter Typen) handelt und keine Chance besteht, dass sie sich weiter entlang der Straße ändern (z. B. in Ihrem Beispiel der Parameter bool).
Ich wusste nichts über den Unterschied bei der Deklaration von .h / .cpp-Dateien, aber es macht Sinn. Auf der Ebene des Maschinencodes ist nichts "const". Wenn Sie also eine Funktion (in der .h) als nicht const deklarieren, ist der Code derselbe, als ob Sie ihn als const deklarieren (abgesehen von Optimierungen). Es hilft Ihnen jedoch, den Compiler zu registrieren, damit Sie den Wert der Variablen in der Implementierung der Funktion (.ccp) nicht ändern. Dies kann nützlich sein, wenn Sie von einer Schnittstelle erben, die Änderungen zulässt, Sie jedoch nicht zu Parametern wechseln müssen, um die erforderliche Funktionalität zu erreichen.
quelle
Ich würde solche Parameter nicht mit const versehen - jeder weiß bereits, dass ein Boolescher Wert (im Gegensatz zu einem Booleschen &) konstant ist. Wenn Sie ihn also hinzufügen, denken die Leute: "Warten Sie, was?" oder sogar, dass Sie den Parameter als Referenz übergeben.
quelle
Die Sache, an die man sich bei const erinnern sollte, ist, dass es viel einfacher ist, Dinge von Anfang an const zu machen, als zu versuchen, sie später einzufügen.
Verwenden Sie const, wenn etwas unverändert bleiben soll - ein zusätzlicher Hinweis, der beschreibt, was Ihre Funktion tut und was Sie erwartet. Ich habe viele C-APIs gesehen, die mit einigen von ihnen funktionieren könnten, insbesondere mit solchen, die C-Strings akzeptieren!
Ich würde eher das const-Schlüsselwort in der cpp-Datei weglassen als den Header, aber da ich dazu neige, sie auszuschneiden + einzufügen, würden sie an beiden Stellen aufbewahrt. Ich habe keine Ahnung, warum der Compiler das zulässt, ich denke, es ist eine Compilersache. Es wird auf jeden Fall empfohlen, Ihr const-Schlüsselwort in beide Dateien einzufügen.
quelle
Es gibt wirklich keinen Grund, einen Wertparameter "const" zu machen, da die Funktion sowieso nur eine Kopie der Variablen ändern kann.
Der Grund für die Verwendung von "const" liegt darin, dass Sie etwas Größeres (z. B. eine Struktur mit vielen Elementen) als Referenz übergeben. In diesem Fall wird sichergestellt, dass die Funktion es nicht ändern kann. oder besser gesagt, der Compiler wird sich beschweren, wenn Sie versuchen, es auf herkömmliche Weise zu ändern. Es verhindert, dass es versehentlich geändert wird.
quelle
Der Parameter Const ist nur dann nützlich, wenn der Parameter als Referenz übergeben wird, dh entweder als Referenz oder als Zeiger. Wenn der Compiler einen const-Parameter sieht, stellt er sicher, dass die im Parameter verwendete Variable nicht im Hauptteil der Funktion geändert wird. Warum sollte jemand einen By-Value-Parameter als Konstante festlegen wollen? :-)
quelle
const
heißt es eindeutig: „Ich muss dies nicht ändern, daher erkläre ich dies. Wenn ich später versuche, es zu ändern, geben Sie mir einen Fehler beim Kompilieren, damit ich meinen Fehler beheben oder die Markierung als deaktivieren kannconst
. ' Es geht also sowohl um Code-Hygiene als auch um Sicherheit. Bei allem, was zum Hinzufügen zu Implementierungsdateien erforderlich ist, sollte es sich um einen reinen Reflex handeln, IMO.Da Parameter als Wert übergeben werden, spielt es keine Rolle, ob Sie const aus Sicht der aufrufenden Funktion angeben oder nicht. Grundsätzlich ist es nicht sinnvoll, Parameter für die Übergabe von Werten als const zu deklarieren.
quelle
Alle Konstanten in Ihren Beispielen haben keinen Zweck. C ++ ist standardmäßig eine Wertübergabe, daher erhält die Funktion Kopien dieser Ints und Booleschen Werte. Selbst wenn die Funktion sie ändert, ist die Kopie des Anrufers nicht betroffen.
Also würde ich zusätzliche Konstanten vermeiden, weil
quelle
Ich weiß, dass die Frage "ein bisschen" veraltet ist, aber als ich darauf stieß, könnte es auch jemand anderes in Zukunft tun ... ... ich bezweifle immer noch, dass der arme Kerl hier unten auflisten wird, um meinen Kommentar zu lesen :)
Es scheint mir, dass wir uns immer noch zu sehr auf die Denkweise im C-Stil beschränken. Im OOP-Paradigma spielen wir mit Objekten herum, nicht mit Typen. Das Const-Objekt kann sich konzeptionell von einem Nicht-Const-Objekt unterscheiden, insbesondere im Sinne von Logical-Const (im Gegensatz zu Bitwise-Const). Selbst wenn die Konstantenkorrektheit von Funktionsparametern (möglicherweise) bei PODs eine Übervorsicht ist, ist dies bei Objekten nicht der Fall. Wenn eine Funktion mit einem const-Objekt arbeitet, sollte sie dies sagen. Betrachten Sie das folgende Code-Snippet
ps.: Sie können argumentieren, dass (const) Referenz hier angemessener wäre und Ihnen das gleiche Verhalten gibt. Nun, richtig. Ich gebe nur ein anderes Bild als das, was ich anderswo sehen konnte ...
quelle