Sollte ich in C / C ++ nach Möglichkeit 'const' in Parametern und lokalen Variablen verwenden?


13

Diese Frage ist inspiriert von einer Frage über finalin Java .

Sollte ich in C / C ++ constwann immer möglich verwenden?

Ich weiß, dass es bereits eine verwandte Frage zur Verwendung constin Parametern gibt . Leider beantworten diese Frage und ihre Antworten meine Frage nicht vollständig, da es sich nur um Funktionsparameter handelt, aber ich würde auch gerne andere Fälle kennenlernen (z. B. lokale Variablen).

Außerdem sagen fast alle Antworten auf diese Frage, dass wir sie verwenden sollten, constda sie nützliche Informationen über die Zugänglichkeit von Variablen enthalten. Dies scheint jedoch im Widerspruch zu einer Antwort über die Verwendung von final in Java zu stehen, deren Zustände finalmöglicherweise überflüssig sind, wenn sie keine zusätzlichen Informationen enthalten. Daher sollte sie weggelassen werden, um den Code kurz und sauber zu halten.

Also, sollte ich constwann immer möglich verwenden? Wenn ja, warum unterscheidet sich der Rat für constin C ++ von dem Rat für finalin Java?

Antworten:


18

Erstens, da Sie sich auf Java bezogen haben final, ist das ein völlig anderes Tier als const. Final bedeutet, dass sich die Referenz nicht ändern kann, aber nichts über Veränderlichkeit aussagt. Const geht weiter und sagt: "Eine Const-Referenz kann nicht mutieren", was eine viel stärkere Garantie darstellt. Dazu muss der interne Status in Java endgültig sein und zum Zeitpunkt der Erstellung festgelegt werden. Const ist viel einfacher zu verwenden und ein vorhandenes Objekt kann in eine const-Referenz "hochgestuft" werden.

Ja, Sie sollten const verwenden, wann immer dies möglich ist. Es wird ein Vertrag geschlossen, dass Ihr Code nichts ändert. Denken Sie daran, dass eine Variable ohne Konstante an eine Funktion übergeben werden kann, die einen Parameter const akzeptiert. Sie können jederzeit const hinzufügen, aber nicht wegnehmen (nicht ohne eine const-Besetzung, was eine wirklich schlechte Idee ist).

Konstante Korrektheit mag manchmal mühsam sein, hilft aber dabei, Unveränderlichkeit zu gewährleisten. Dies ist bei Multithread-Code von entscheidender Bedeutung, bei dem Threads Objekte gemeinsam nutzen. Dadurch werden bestimmte Aufgaben effizienter: Anstatt den Status zu kopieren, verwenden Sie einfach dasselbe unveränderliche Objekt erneut. Bibliotheken akzeptieren möglicherweise const-Parameter, um dem Programmierer die Garantie zu geben, dass sich Ihr Objekt im Schwarzen Loch, das den Mut der Bibliothek ausmacht, nicht auf unvorhersehbare Weise ändert.


1
Stimmen Sie ab, weil Sie das erklären finalund constnicht die gleichen Garantien haben.
Bill Door

2
Bei Konstanz geht es um Schreibbarkeit, nicht um Veränderlichkeit.
Basilevs

@ Basilevs Was passiert, wenn Sie in ein Objekt schreiben? Es mutiert. Wie mutiert man ein Objekt? Schreiben Sie darauf.

4
Was passiert, wenn Sie in eine const-Referenz schreiben? Ein Fehler bei der Kompilierung. Was passiert, wenn Sie in das Objekt schreiben, auf das irgendwo durch eine const-Referenz über eine andere nicht-const-Referenz verwiesen wird? Es mutiert. Unveränderliches Objekt kann nicht mutieren, daher verweist const refernce nicht unbedingt auf unveränderliches Objekt.
Basilevs

@Basilevs Ihre Beobachtung gilt nur für const refs. Wenn ein Objekt selbst als const deklariert wird (nicht nur als Referenz), ist es mehr oder weniger unveränderlich (es sei denn, jemand wirft die constness schändlich weg).
Matthew James Briggs

4

Persönlich constbrauche ich sehr wenig Zeit zum Schreiben und sehr wenig Zeit zum Lesen, normalerweise viel weniger als zum Überprüfen, ob ein Code die Variable mutiert, und es hindert mich tatsächlich daran, Fehler zu schreiben (hat jemand jemals versehentlich seinen Enditerator erhöht? Usw)

Ich finde auch, dass mich die strikte Verwendung von const auf andere Weise zu besserem Code führt, z. B. zum Erstellen von Hilfsfunktionen für nicht triviale Initialisierungen.


4

Ich werde mit den anderen Postern nicht einverstanden sein und empfehlen, keine Top-Level constfür lokale Variablen und Parameter zu verwenden. (Verweise und Verweise auf const, dh const T&, sind unterschiedlich, und Sie sollten sie jederzeit zur Richtigkeit verwenden, wenn dies angemessen ist.)

Die Vorteile von Top-Level constsind:

  • Verdeutlicht, dass die lokalen Variablen nicht mutiert werden sollen.
  • Gibt einen Compilerfehler aus, wenn Sie versehentlich versuchen, sie zu mutieren.

Die Nachteile sind:

  • Visuelle Unordnung.
  • Kann nicht für "Pseudo-Const" -Variablen verwendet werden, dh Variablen, die auf eine Weise komplizierter als die direkte Konstruktion initialisiert werden, aber danach nicht geändert werden, z. B getline.:

    std::string line; // cannot be const
    std::getline(std::cin, line);
    // line should be const from here on out
  • Verhindert die Auszugsoptimierung bei Funktionsaufruf und Rückgabe:

    std::string f1();
    std::string f2(std::string s);
    std::string f3() {
      const std::string s = f1(); // s is not meant to be modified
      // but I still want the move optimization here:
      const std::string result = f2(std::move(s)); // this doesn't move
      // and I want the compiler to move out here:
      return result; // this will probably RVO, but if not, the move
                     // constructor will not be used due to the const
    }

Ich habe an einer Codebasis gearbeitet, in der local häufig constverwendet wurde, und fand sie überhaupt nicht hilfreich, aber sie füllte den Code wie oben mit subtilen Pessimisierungen. Ich persönlich bevorzuge eine allgemeine Richtlinie, bei der Variablen so selten wie möglich geändert werden und Funktionen so klein gemacht werden, dass die Verwendung einer Variablen offensichtlich ist, und selbst wenn sie geändert wird, ist die Komplexität der Funktion gering genug, um sie zu einer Nicht-Funktion zu machen -Problem.


2
Ihr Punkt über das Verschieben von ist, zu zeigen, wo Sie das lokale nicht in einer konstanten Weise verwenden, wie Sie (beabsichtigen), es mit dem Verschieben zu ändern
Caleth

1
@ Caleth Nein, das ist der Punkt. Ich habe nicht vor, es zu ändern. Ich möchte nur den Wert übergeben oder zurückgeben, und ich möchte, dass er effizient ist. Konzeptionell ist die Änderung nur eine Optimierung, die nicht beobachtbar sein soll (da die Variablen danach nicht mehr verwendet werden). Praktisch, ja, es gibt eine Modifikation, da C ++ keine echten destruktiven Bewegungen hat (wie Rust). Genau deshalb möchte ich nicht constauf Einheimische: weil es technische Änderungen verhindert, nicht nur konzeptionelle Änderungen.
Sebastian Redl

2
Sie möchten den Wert nicht ändern , aber Sie möchten die Variable ändern . Sie können stattdessen const & verwenden und keine ändern
Caleth

2

Das constSchlüsselwort sollte genau wie Parameter für lokale Variablen verwendet werden. Es ist nützlich, weil:

  • Einfacher, den Code zu lesen. Wenn jemand die Variablendeklaration liest, weiß er, dass sie sich nicht ändert. Eine Sache weniger, die Sie beim Lesen Ihres Codes befürchten müssen.
  • Verhindern Sie, dass Sie die Variable versehentlich ändern
  • Keine Laufzeitstrafe, alles wird statisch überprüft. Es ist wie ein kostenloses Mittagessen, constsollte nur eine Sekunde dauern , um zu schreiben, also ist es keine große Sache.
  • Es ist immer eine gute Idee, Ihre Variablen / Parameter in Ihren Multithread-Anwendungen zu erstellen. Auch wenn Ihre Anwendung kein Multithreading ist, ist sie dennoch eine gute Angewohnheit.
  • Sie geben Ihrem C ++ - Compiler die Möglichkeit, Ihren Code zu optimieren.

Beachten Sie, dass es hier keine richtige / falsche Antwort gibt. In Ihrem Link sollte der Antwortende, der die meisten positiven Stimmen erhalten hat, finalnicht lokal verwendet werden. Der nächste Antwortende empfahl es jedoch nachdrücklich.

Wenn Ihre Funktion einfach und trivial ist , sollten Sie sie nicht hinzufügen, constda jeder Ihre Absicht versteht. Wenn die Logik in Ihrer Funktion jedoch nicht trivial ist, sollten Sie das Schlüsselwort verwenden. Denken Sie daran, es gibt wenig zu verlieren.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.