542 Stimmen

Verwendung von 'const' für Funktionsparameter

Wie weit gehen Sie mit const ? Machen Sie einfach Funktionen const wenn es nötig ist, oder gehen Sie aufs Ganze und verwenden es überall? Stellen Sie sich zum Beispiel einen einfachen Mutator vor, der einen einzigen booleschen Parameter annimmt:

void SetValue(const bool b) { my_val_ = b; }

Ist das const tatsächlich nützlich? Ich persönlich entscheide 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 man die const von Parametern in einer Funktionsdeklaration, sondern kann sie in die Funktionsdefinition aufnehmen, z. B.:

.h-Datei

void func(int n, long l);

.cpp-Datei

void func(const int n, const long l)

Gibt es dafür einen Grund? Es erscheint mir ein wenig ungewöhnlich.

38voto

QBziZ Punkte 3006

Const sollte der Standard in C++ sein. Zum Beispiel so:

int i = 5 ; // i is a constant

var int i = 5 ; // i is a real variable

25voto

Gabriel Staples Punkte 20228

1. Beste Antwort auf der Grundlage meiner Einschätzung:

Die Antwort von @Adisak ist nach meiner Einschätzung hier die beste Antwort. Beachten Sie, dass diese Antwort zum Teil die beste ist, weil sie auch le site am besten mit echten Code-Beispielen untermauert , zusätzlich zur Anwendung einer soliden und gut durchdachten Logik.

2. Meine eigenen Worte (ich stimme der besten Antwort zu):

  1. Bei Pass-by-Value ist es nicht sinnvoll, die const . Alles, was es tut, ist:
    1. schränken den Implementierer ein, jedes Mal eine Kopie erstellen zu müssen, wenn er einen Eingabeparameter im Quellcode ändern will (die Änderung hätte ohnehin keine Nebeneffekte, da das, was übergeben wird, bereits eine Kopie ist, da es sich um eine Wertübergabe handelt). Und häufig wird das Ändern eines Eingabeparameters, der als Wert übergeben wird, verwendet, um die Funktion zu implementieren, so dass das Hinzufügen von const können dies überall behindern.
    2. und Hinzufügen const überfrachtet den Code unnötig mit const und lenkt so die Aufmerksamkeit von den const s, die wirklich notwendig sind, um sicheren Code zu haben.
  2. Beim Umgang mit Zeiger o Referenzen Allerdings, const ist im Bedarfsfall von entscheidender Bedeutung, und muss verwendet werden, da sie unerwünschte Nebenwirkungen bei anhaltenden Veränderungen verhindert außerhalb die Funktion und somit jeder einzelne Zeiger oder Verweis muss verwenden. const wenn der Parameter nur eine Eingabe, nicht aber eine Ausgabe ist. Verwendung von const nur für Parameter, die als Referenz oder Zeiger übergeben werden, hat den zusätzlichen Vorteil, dass sie ganz offensichtlich welche Parameter Zeiger oder Referenzen sind. Das ist eine weitere Sache, die auffällt und sagt: "Achtung! Jeder Parameter mit const daneben ist ein Verweis oder Zeiger!".
  3. Was ich oben beschrieben habe, war häufig der Konsens in den professionellen Software-Organisationen, in denen ich gearbeitet habe, und wurde als beste Praxis angesehen. Manchmal war die Regel sogar streng: "Verwenden Sie const niemals bei Parametern, die als Wert übergeben werden, sondern immer bei Parametern, die als Referenz oder Zeiger übergeben werden, wenn es sich nur um Eingaben handelt."

3. Googles Worte (stimmt mit mir überein und ist die beste Antwort):

(Aus dem " Google C++ Style Guide ")

Bei einem Funktionsparameter, der als Wert übergeben wird, hat const keine Auswirkungen auf den Aufrufer und wird daher in Funktionsdeklarationen nicht empfohlen. Siehe TotW #109 .

Die Verwendung von const für lokale Variablen wird weder empfohlen noch abgeraten.

Quelle: Der Abschnitt "Use of const" des Google C++ Style Guide: https://google.github.io/styleguide/cppguide.html#Use_of_const . Dies ist ein wirklich wertvoller Abschnitt, also lesen Sie den ganzen Abschnitt.

Hinweis: "TotW #109" steht für "Tipp der Woche #109: Bedeutungsvoll const in Funktionsdeklarationen" und ist auch eine nützliche Lektüre. Es ist informativer und weniger präskriptiv, was zu tun ist, und basiert auf Kontext kam vor die Regel des Google C++ Style Guide zu const zitiert, aber aufgrund der Klarheit, die sie verschafft, ist die const Die oben zitierte Regel wurde in den Google C++ Style Guide aufgenommen.

Beachten Sie auch, dass ich hier zwar den Google C++ Style Guide zitiere, um meine Position zu verteidigen, dies aber NICHT bedeutet, dass ich den Guide immer befolge oder immer empfehle, den Guide zu befolgen. Einige der dort empfohlenen Dinge sind einfach nur seltsam, wie z. B. ihre kDaysInAWeek -Style Namenskonvention für "Constant Names" . Dennoch ist es nützlich und relevant, darauf hinzuweisen, wenn eines der weltweit erfolgreichsten und einflussreichsten Technik- und Softwareunternehmen dieselbe Begründung verwendet wie ich und andere wie @Adisak, um unsere Standpunkte zu diesem Thema zu untermauern.

4. Clang's Linter, clang-tidy hat dafür einige Möglichkeiten:

A. Es ist auch erwähnenswert, dass Clang's linter, clang-tidy hat eine Option, readability-avoid-const-params-in-decls , hier beschrieben zu unterstützen. Durchsetzung in einer Codebasis no mit const für Wertübergabe-Funktionsparameter :

Prüft, ob eine Funktionsdeklaration Parameter hat, die Top-Level-Consts sind.

const-Werte in Deklarationen haben keinen Einfluss auf die Signatur einer Funktion und sollten daher dort nicht eingefügt werden.

Beispiele:

void f(const string);   // Bad: const is top level.
void f(const string&);  // Good: const is not top level.

Und hier sind zwei weitere Beispiele, die ich der Vollständigkeit und Klarheit halber selbst hinzugefügt habe:

void f(char * const c_string);   // Bad: const is top level. [This makes the _pointer itself_, NOT what it points to, const]
void f(const char * c_string);   // Good: const is not top level. [This makes what is being _pointed to_ const]

B. Es hat auch diese Option: readability-const-return-type - https://clang.llvm.org/extra/clang-tidy/checks/readability-const-return-type.html

5. Mein pragmatischer Ansatz, wie ich einen Style Guide zu diesem Thema formulieren würde:

Ich würde das einfach kopieren und in meinen Style Guide einfügen:

[COPY/PASTE START]

  1. Verwenden Sie immer const bei Funktionsparametern, die per Verweis oder Zeiger übergeben werden, wenn ihr Inhalt (worauf sie zeigen) NICHT geändert werden soll. Auf diese Weise wird deutlich, wenn eine per Verweis oder Zeiger übergebene Variable geändert werden soll, da sie keine const . In diesem Anwendungsfall const verhindert unbeabsichtigte Nebeneffekte außerhalb der Funktion.
  2. Sie ist nicht empfohlen zu verwenden const für Funktionsparameter, die als Wert übergeben werden, da const hat keine Auswirkungen auf den Aufrufer: Selbst wenn die Variable in der Funktion geändert wird, gibt es keine Nebeneffekte außerhalb der Funktion. In den folgenden Ressourcen finden Sie weitere Begründungen und Einblicke:
    1. "Google C++ Style Guide" Abschnitt "Verwendung von const"
    2. "Tipp der Woche #109: Bedeutungsvoll const in Funktionsdeklarationen"
    3. Stack Overflow-Antwort von Adisak auf "Verwendung von 'const' für Funktionsparameter"
  3. " Verwenden Sie niemals Top-Level const [d.h.: const zu den Parametern nach Wert übergeben ] auf Funktionsparameter in Deklarationen, die keine Definitionen sind (und achten Sie darauf, dass Sie nicht einen sinnlosen Text kopieren/einfügen const ). Es ist bedeutungslos und wird vom Compiler ignoriert, es ist visuelles Rauschen und könnte die Leser in die Irre führen" ( https://abseil.io/tips/109 (Hervorhebung hinzugefügt).
  4. Die einzige 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.
  5. Verwenden Sie niemals Top-Level const [d.h.: const auf Variablen nach Wert übergeben ] auf Werte zurückgegeben durch eine Funktion.
  6. Verwendung von const auf Zeiger oder Referenzen, die von einer Funktion zurückgegeben werden, ist bis zum Umsetzer da sie manchmal nützlich ist.
  7. TODO: Durchsetzung einiger der oben genannten Punkte durch folgende Maßnahmen clang-tidy Optionen:
  8. https://clang.llvm.org/extra/clang-tidy/checks/readability-avoid-const-params-in-decls.html
  9. https://clang.llvm.org/extra/clang-tidy/checks/readability-const-return-type.html

Hier sind einige Code-Beispiele zur Veranschaulichung der const oben beschriebenen Regeln:

const Beispiele für Parameter:
(einige sind entlehnt aus ici )

void f(const std::string);   // Bad: const is top level.
void f(const std::string&);  // Good: const is not top level.

void f(char * const c_string);   // Bad: const is top level. [This makes the _pointer itself_, NOT what it points to, const]
void f(const char * c_string);   // Good: const is not top level. [This makes what is being _pointed to_ const]

const Beispiele für Rückgabetypen:
(einige sind entlehnt aus ici )

// BAD--do not do this:
const int foo();
const Clazz foo();
Clazz *const foo();

// OK--up to the implementer:
const int* foo();
const int& foo();
const Clazz* foo();

[KOPIEREN/EINFÜGEN ENDE]

Schlüsselwörter: Verwendung von <code>const</code> in Funktionsparametern; Codierungsstandards; C- und C++-Codierungsstandards; Codierungsrichtlinien; bewährte Praktiken; Codestandards; konstante Rückgabewerte

24voto

Avdi Punkte 18202

Als ich beruflich C++ programmiert habe, habe ich alles, was ich konnte, in Betracht gezogen. Die Verwendung von const ist eine großartige Möglichkeit, dem Compiler zu helfen, Ihnen zu helfen. Wenn Sie zum Beispiel die Rückgabewerte Ihrer Methoden mit Konstanten versehen, können Sie Tippfehler vermeiden, wie z. B.:

foo() = 42

wenn Sie meinten:

foo() == 42

Wenn foo() so definiert ist, dass es eine Nicht-Konst-Referenz zurückgibt:

int& foo() { /* ... */ }

Der Compiler lässt Sie dem anonymen Zwischenspeicher, der vom Funktionsaufruf zurückgegeben wird, gerne einen Wert zuweisen. Es const machen:

const int& foo() { /* ... */ }

Das schließt diese Möglichkeit aus.

15voto

Void Punkte 3351

Es gibt eine gute Diskussion zu diesem Thema in den alten "Guru der Woche" Artikeln auf comp.lang.c++.moderated ici .

Der entsprechende GOTW-Artikel ist auf Herb Sutters Website zu finden ici .

10voto

Asaf R Punkte 6700

Ich verwende const bei Funktionsparametern, die Referenzen (oder Zeiger) sind, die nur [in] Daten sind und von der Funktion nicht verändert werden. Das heißt, wenn der Zweck der Verwendung einer Referenz darin besteht, das Kopieren von Daten zu vermeiden und keine Änderung des übergebenen Parameters zu ermöglichen.

Die Verwendung von const für den Parameter boolean b in Ihrem Beispiel stellt nur eine Einschränkung für die Implementierung dar und trägt nicht zur Schnittstelle der Klasse bei (obwohl es normalerweise ratsam ist, Parameter nicht zu ändern).

Die Funktionssignatur für

void foo(int a);

et

void foo(const int a);

gleich ist, was Ihre .c und .h erklärt

Asaf

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X