Warum sollten Sie das Schlüsselwort const verwenden, wenn Sie bereits wissen, dass die Variable konstant sein sollte?

70

Viele der Bücher, die ich lese, verwenden Schlüsselwörter, constwenn der Wert einer Variablen nicht geändert werden soll. Abgesehen davon, dass Sie den Lesern des Codes mitteilen, dass Sie beim Ändern dieser Variablen Fehler verursachen können (Sie können dazu Kommentare verwenden), warum benötigen Sie dieses Schlüsselwort, um Teil einer Programmiersprache zu sein? Mir scheint, wenn Sie keine Variable ändern möchten, tun Sie dies einfach nicht.

Könnte jemand das für mich klären?

FutureSci
quelle
42
Warum geschützt oder privat verwenden? Oder abstrakt? Oder endgültig?
Oliver Charlesworth
9
Denken Sie daran, dass viele Schlüsselwörter und Konzepte Programmierern und nicht Programmen helfen sollen. constist ein bisschen von beidem.
Keyser
72
Das Weglassen constwürde sehr gut für Programmierer funktionieren, die niemals Fehler machen.
Keith Thompson
26
Stroustrup drückte es am besten aus: Compiler lesen keine Kommentare. Vielleicht denken Sie, Sie können Regeln besser befolgen als ein Compiler.
DanielKO
33
Bei der Programmierung eingebetteter Systeme bietet ein constBezeichner dem Compiler und Linker die Möglichkeit, die Adresse des Werts einem EPROM-Speicherabschnitt anstatt im RAM zuzuordnen. Ich habe vor vielen Jahren an einem System gearbeitet, das dieses Verhalten für vorab zugewiesene statische Variablen hatte (bevor das constSchlüsselwort eingeführt wurde).
Lurker

Antworten:

100

Abgesehen davon, dass Sie den Lesern des Codes mitteilen, dass Sie beim Ändern dieser Variablen Fehler verursachen können (Sie können dazu Kommentare verwenden).

Nicht "darf"; wird Fehler in Ihrem Programm verursachen.

  • Ein C ++ - Compiler erzwingt dies mit Kompilierungsfehlern und Diagnosemeldungen ("Compilerfehler"), ohne dass Kommentare erforderlich sind.
  • Der AC-Compiler wird es größtenteils erzwingen , obwohl seine Standardbibliothek aufgrund von Legacy-Lücken wie z. B. strchrLücken aufweist und einige eher milde implizite Konvertierungsregeln enthält, mit denen Sie constNess löschen können, ohne es ganz einfach zu bemerken. Nur weil Sie eine erfolgreiche Kompilierung erhalten haben, bedeutet dies nicht, dass Sie keine Fehler haben. Leider bedeutet dies, dass die Fehler subtile Fehler in Ihrem Programm sowie große, spektakuläre Abstürze sein können.

In jedem Fall enthält Ihr Programm garantiert einen Fehler .

Mir scheint, wenn Sie keine Variable ändern möchten, tun Sie dies einfach nicht.

Nun, das ist alles schön und gut, aber niemand ist perfekt. Programmierer machen Fehler. Auf diese Weise kann der Compiler - der (zumindest normalerweise nicht) niemals Fehler macht - Sie darauf hinweisen.

Dies ist besonders nützlich, wenn Sie eine Datenvariable verwenden, die viele, viele Codezeilen von dem Ort entfernt ist, an dem sie erstellt wurde. Je weiter es entfernt ist, desto einfacher ist es, es zu ändern, ohne zu bemerken, dass Sie es nicht sollten. Für große, komplexe Codebasen ist dies einfach ein Muss.

Sie erhalten ein neues Maß an Beweisbarkeit , Korrektheit und Stabilität in Ihrer Codebasis sowie eine große Menge möglicher Ursachen für wirklich subtile und böse Fehler. Es gibt auch große Optimierungsmöglichkeiten für Ihren Compiler (in einigen Fällen), wenn er weiß, dass sich ein Wert nach dem Kompilieren nicht ändert.

Wir könnten die Vorteile den ganzen Tag auflisten , aber Sie werden es wirklich nicht vollständig verstehen , bis Sie an einer solchen Codebasis gearbeitet haben.

In einer perfekten Welt wären conststandardmäßig alle Variablen vorhanden , und Sie müssten sie mit dem Schlüsselwort deklarieren mutable, um sie ändern zu können. C ++ ist rückwärts.

Leichtigkeitsrennen im Orbit
quelle
17
Ich möchte in dieser perfekten Welt leben!
Captain Obvlious
1
Scala ist diese perfekte Welt: Unveränderlichkeit wird gefördert, Sammlungsklassen sind standardmäßig unveränderlich und Sie benötigen ein bestimmtes Schlüsselwort var, um nicht veränderbare Variablen zu deklarieren.
Ouah
21
@ouah: Scala ist nicht wirklich die perfekte Welt. Es fördert die Unveränderlichkeit. Haskell (zum Beispiel) erzwingt es.
Jerry Coffin
22
"In einer perfekten Welt wären alle Variablen standardmäßig const": Würden sie nicht als unveränderliche Variablen bezeichnet?
JulianSymes
2
+1. Nach einigen Erfahrungen mit Haskell und gleichzeitiger Programmierung bin ich zu dem gleichen Schluss gekommen, dass "alle Variablen standardmäßig const sind" . In der Tat ist es philosophisch unsolide , wenn eine Variable ist wandelbar standardmäßig . Es hat das gleiche philosophische Problem, wenn Mitglieder einer Klasse standardmäßig öffentlich sind .
Nawaz
41

Zumindest in C ++ consthat es einige Verwendungszwecke, die über die Dokumentation Ihrer Absicht gegenüber anderen Programmierern hinausgehen.

constkann dem Compiler auch einige Dinge mitteilen. Beispielsweise kann eine Funktion, die eine Referenz verwendet, wie z. B.: void f(T &t);Ein temporäres Objekt nicht als Parameter akzeptieren. Um dies zu erreichen, müssen Sie constdie Referenz wie folgt qualifizieren : void f(T const &t).

Um eine Elementfunktion für ein const-Objekt aufzurufen, muss die constElementfunktion wie folgt qualifiziert sein : void T::foo() const {}.

In einem eingebetteten System const kann dies noch mehr bedeuten und dem Compiler möglicherweise mitteilen, wo sich das betreffende Objekt befindet (in ROM oder RAM). constallein reicht nicht unbedingt aus, um "dieses Objekt in ROM zu setzen", aber es ist immer noch oft eine Voraussetzung.

Ebenso (unter C ++ 11) const informiert der Compiler über die Thread-Sicherheit .

Nun ist es zweifellos wahr, dass Sie eine andere Sprache definieren könnten, die (auf andere Weise) Ähnlichkeit mit C oder C ++ hatte, die constauf diese Weise nicht verwendet wurden . Das Ergebnis wäre jedoch eine andere Sprache als beide. Ohne Ihre Absicht zu kennen, ist es unmöglich zu sagen, wie es ausgehen würde, aber es könnte näher an Java oder C # (für einige Beispiele) enden, die beide in gewisser Weise C und C ++ etwas ähnlich sind, aber nicht in dieser Hinsicht eins (dh nicht constwie C und C ++ verwenden).

Jerry Sarg
quelle
constWenn ich mich recht erinnere, wird Java überhaupt nicht verwendet . (Ich denke, es ist ein reserviertes Wort, aber für nichts verwendbar.) Das finalSchlüsselwort ist ähnlich, aber nicht ganz dasselbe. C # hat const, aber es ist nicht dasselbe. (Ich denke, es ist meistens nur gleichbedeutend mit #defines.)
Darrel Hoffman
38

Neben den üblichen Programmierüberlegungen, die bereits in anderen Antworten erörtert wurden, geht mir vor allem die Einstellung an:

Mir scheint, wenn Sie keine Variable ändern möchten, tun Sie dies einfach nicht.

Als Faustregel gilt, dass 20% der Kosten für das Schreiben von Code in der Entwicklungsphase aufgewendet werden. Die anderen 80% werden über die gesamte Lebensdauer des Codes ausgegeben, um ihn zu aktualisieren, zu warten usw. Dies bedeutet, dass viele andere Personen als Sie an Ihrem Code arbeiten.

Zeit, die während der Entwicklung aufgewendet wird, um Probleme Jahre später zu vermeiden, ist eine gute Investition. Diese Bemühungen umfassen: Schreiben von Kommentaren; Konstanten definieren, die Konstanten sind; und Schreiben von explizitem Code, der nicht auf obskuren Sprachkonstrukten beruht.

Außerdem, @worlboss, höre ich einiges an Intoleranz. Wie einige andere kommentiert haben, machen Kohlenstoffeinheiten Fehler und alles, was eine Siliziumeinheit tun kann, um Fehler zu vermeiden, wird geschätzt.

JackCColeman
quelle
9
+1 für die Erwähnung der 80% in der Wartung, die die meisten Leute vergessen.
Thomas Matthews
Diese 20% scheinen hoch zu sein. Es könnte 20% sein, wenn am Anfang alles richtig gemacht wurde. Leider scheint das nicht immer zu passieren.
user606723
@ user606723, das ist eine Faustregel. Wenn die Entwicklungsphase mehr kostet als geplant, erhöhen sich 20% als Bruchteil der gesamten Lebensdauerkosten der Software.
JackCColeman
1
@ JackCColeman, ich sagte, dass 20% hoch scheinen. Ich denke, es ist fast 10-15%
user606723
21

Es teilt dem Compiler mit, dass die Variable nicht geändert werden soll. Wenn also jemand Code schreibt, der sie ändert, kennzeichnet der Compiler sie als Fehler.

edtheprogrammerguy
quelle
2
Ich wette, die leistungsbezogenen Vorteile waren zu diesem Zeitpunkt ebenfalls sehr wichtig.
Chris
17

Zwei Gründe:

  1. Compiler erzwungene Dokumentation
  2. Compiler-Optimierungen

Hier ist eine gute Erklärung von Ian Lance Taylor (der an gccund goldLinker gearbeitet hat):

Die erste Bedeutung von const hat einen echten Einfluss auf das Programm. Eine als const deklarierte Variable kann anders kompiliert werden als eine Variable, die nicht als const deklariert ist.

Die zweite Bedeutung von const ist in der Tat die vom Compiler erzwungene Dokumentation. Der Compiler gibt einen Fehler aus, wenn versucht wird, einen Wert mithilfe eines const-qualifizierten Zeigers zu ändern. Wenn Sie jedoch einen solchen Zeiger deklarieren, wird der generierte Code nicht geändert.

ouah
quelle
@ LightnessRacesinOrbit vielleicht, weil Sie für API sicherlich constnur mit
Zeigerparametern verwenden
1
@ouah: Was? Nein, tut es nicht. constin der Tat wird ignoriert (der Sprache) auf Argumente (ob sie Zeiger oder nicht irrelevant ist, Sie sprechen über die Anwendung constder zugrunde liegenden pointee Typ anstelle der Funktionsargument Typ selbst) in Erklärungen, weil es sinnlos. Es ist nur sinnvoll , für die lokalisierte constness in der Funktionsdefinition . Wie kann es sich also auf die API auswirken?
Leichtigkeitsrennen im Orbit
3
[C++11: 8.3.5/3]: [..] Nach dem Erstellen der Liste der Parametertypen werden alle Lebenslaufqualifizierer der obersten Ebene, die einen Parametertyp ändern, beim Bilden des Funktionstyps gelöscht . [..]
Leichtigkeitsrennen im Orbit
1
[C99: 6.7.5.3/15]: [..] (Bei der Bestimmung der Typkompatibilität und eines zusammengesetzten Typs wird für jeden mit Funktions- oder Array-Typ deklarierten Parameter der angepasste Typ und für jeden mit qualifiziertem Typ deklarierten Parameter die nicht qualifizierte Version seines deklarierten Typs angenommen .) [..]
Leichtigkeitsrennen im Orbit
1
^ Die API (Funktionsdeklarationen ) bekommen nicht einmal zu sehen , die consts. Re-Anwendung in den Funktionsdefinitionen ist nicht relevant.
Leichtigkeitsrennen im Orbit
6

Hier ist ein einfaches C-Beispiel:

void PrintList(const struct List *l);
void SortList(struct List *l);
int  CmpList(const struct List *a, const struct List *b);
void AppendList(struct List *l, struct List *m);
void PushList(struct List *l, struct ListNode *n);
void PopList(struct List *l, struct ListNode *n);

Hier haben wir eine kleine Reihe von Funktionen, die mit einer Art Liste von Knoten arbeiten. Erstens, ohne die Namen der Funktionen zu kennen, können wir sofort sehen, welche Funktionen unsere Liste auf irgendeine Weise ändern und welche nicht. Die constFunktionen, wie in den Standardbibliotheken, ändern Ihre Daten nicht und ermöglichen es Ihnen nicht, Ihre Daten mit ihnen zu ändern. Der C-Compiler versucht, die const-ness der Zeiger beizubehalten, die auf die Daten erzwungen werden, die Sie an die Funktionen übergeben. In diesem Fall kann ich also ziemlich sicher sein, dass das Vergleichen von zwei Listen nicht die Funktion ist, die sie beim Debuggen zur Laufzeit beeinträchtigt, da ich mich vor versehentlichen Änderungen an meinen Daten geschützt habe. ;)

CyberSkull
quelle
5

Ihr Compiler kann große Optimierungen vornehmen, da er weiß, dass eine Variable nicht geändert wird: Anstatt sie im Speicher zu speichern, wird sie direkt in den ausführbaren Opcode geschrieben.

Beispiel: Sie haben a und b, Sie möchten sie hinzufügen, Sie machen a + b. Wenn Sie a als const und mit dem Wert 3 deklarieren, macht das Programm stattdessen 3 + b, wodurch Speicher und Zyklen gespart werden, da der a-Wert nicht abgerufen werden muss.

Das Problem ist, dass Ihr Compiler nicht im Voraus wissen kann, ob Variablen konstant sind oder nicht. Natürlich könnte er den gesamten Code analysieren und prüfen, ob Sie solche Variablen geändert haben, aber es ist nicht 100% sicher, da zukünftiger Code ihn auch ändern kann.

Jokoon
quelle
4

Das Schlüsselwort constist sehr nützlich für Teams und langfristige Projekte. Ich gebe Ihnen einige Beispiele, die den Wert des constSchlüsselworts erklären sollten .

Nehmen wir an, ich erstelle jetzt eine Bibliothek, die für weitere Projekte verwendet wird. Das bedeutet, dass der heute geschriebene Code nach einigen Jahren vertrauenswürdig sein muss. In einem solchen Zeitraum werde ich wahrscheinlich vergessen, welche Variable nicht geändert werden sollte (Kollegen wissen sogar nicht, was geändert werden kann und was nicht). Dieses kurze Beispiel erklärt also, warum zu verwenden const.

Über Kommentare zu sprechen, wenn die Frist kommt und es viele Dinge gibt, die immer noch nicht zu jeder Funktion funktionieren, wäre nur Zeitverschwendung. In einigen Fällen sind Kommentare jedoch ein Muss, da Kommentare aufgrund des ersten Problems (Frist) möglicherweise nicht gelesen werden, da die meisten nutzlos sind, wichtige Kommentare jedoch auch übersprungen werden. Es ist daher besser, ein constSchlüsselwort zu verwenden, das einen Kompilierungsfehler verursacht und Sie auf das Problem hinweist, als viele Kommentare zu schreiben und zu lesen.

ST3
quelle
2

Dies ist eine schwierige Frage, da IMO auf Überzeugungen basiert. Eine dieser Überzeugungen ist, dass Sie Ihren Code vor Änderungen schützen können, indem Sie einfach mehr Code hinzufügen. Natürlich wird dieser zusätzliche Code vom Compiler verwendet, um zu überprüfen, ob alles in Ordnung ist.

Ich denke, das ist nicht immer richtig. Sie können Ihren Code nicht vor sich selbst oder Ihrem Entwicklungsteam schützen, indem Sie nur Schlüsselwörter hinzufügen. Tatsächlich gibt es viele Sprachen, die keine const, public, private, protected, internal, int, float, haben. doppelte Schlüsselwörter und das bedeutet nicht, dass sie keine guten Sprachen sind.

Das gleiche passiert mit einigen Codemustern. Warum haben die Leute so viel Zeit damit verschwendet, über Singletons zu diskutieren? Wenn Sie nur eine Instanz haben möchten, müssen Sie nur eine Instanz erstellen, das ist alles. Die gleiche Denkweise gibt es überall. Schauen Sie sich die vor 10 Jahren veröffentlichten Artikel zur defensiven Programmierung an, noch einmal die Idee, Code mit Code zu schützen.

Irgendwann müssen Sie entscheiden, wo Sie die Verantwortlichkeiten festlegen möchten, bei den Entwicklern oder bei den Compilern. Allerdings kann weder der Compiler noch ein anderes Tool den Code gegen die Entwickler speichern. Aus diesem Grund sind viele Schlüsselwörter wertlos oder nur eine Möglichkeit, anderen Entwicklern etwas mitzuteilen.

lontivero
quelle
1

Mit konstanten Variablen können Sie nur besser lesbaren Code schreiben.

In constfast allen Sprachen wird am häufigsten verwendet , damit wir Namen verwenden können, um auf Konstantenwerte zu verweisen, sodass Sie anderen in fließender Sprache mitteilen können, worauf sich dieser Name bezieht, ohne Kommentare in Ihrem Code verbreiten zu müssen und Zeit und Mühe zu sparen von den Lesern, um den Parametertyp und die Besonderheiten der Parameter zu kennen. Natürlich profitieren Sie auch davon, wenn Ihr konstanter Wert in Ihrem Code wiederverwendet wird. Ein Code wie dieser kann besser lesbar sein:

processPages(LETTER_PAPER_WIDTH, LETTER_PAPER_HEIGHT);

...als das:

processPages(215.9, 279.4); // 8.5 x 11 Inches in millimeters for Letter Papers

Im obigen Beispiel müssen Sie verstehen, was jeder Parameter ist, seine Einheit und der Typ, um die Werte zu interpretieren, und Sie müssen ihn noch anhand des Kommentars validieren, da ein redundanter Kommentar wie dieser (die Kommentare, die das wiedergeben, was codiert ist) ist kein zuverlässiger und so nützlicher Kommentar (ist ein schlechter Kommentar laut Robert Martin in Clean Code: http://goo.gl/5EyY ).

Luciano
quelle
-2

Stellen Sie sich das Szenario vor, in dem Sie in Ihrem gesamten Projekt häufig dieselben Konstanten verwenden und diese an allen Stellen hart codieren. Jetzt müssen Sie plötzlich den Wert der Konstanten in einen anderen Wert ändern, sodass es hektisch ist, Änderungen an allen Standorten vorzunehmen.

Daher denke ich, dass es einer der Gründe ist, Ihren Code wartbarer zu machen.

Mohan Mahajan
quelle
3
-1. Ihre Antwort ist zwar an sich wahr, hat aber wenig mit der gestellten Frage zu tun. Die Frage war, warum der const-Modifikator verwendet werden soll. Die Antwort lautet, warum an einem einzigen Ort definiert werden soll.
Emilio M Bumachar
Ich gebe meinen Fehler zu, die Frage anders herum zu stellen. Entschuldigung, mein Fehler!
Mohan Mahajan