[C++] Verwendung von 'const' für Funktionsparameter


Answers

"const ist sinnlos, wenn das Argument an Wert übergeben wird, da Sie das Objekt des Aufrufers nicht ändern werden."

Falsch.

Es geht darum, Ihren Code und Ihre Annahmen selbst zu dokumentieren.

Wenn Ihr Code viele Leute hat, die daran arbeiten und Ihre Funktionen nicht trivial sind, dann sollten Sie "const" markieren und alles, was Sie können. Wenn Sie industriellen Code schreiben, sollten Sie immer davon ausgehen, dass Ihre Mitarbeiter Psychopathen sind, die versuchen, Sie so weit wie möglich zu bringen (vor allem, weil Sie es oft selbst in der Zukunft sind).

Wie bereits erwähnt, könnte es dem Compiler dabei helfen, die Dinge ein wenig zu optimieren (obwohl es eine lange Geschichte ist).

Question

Wie weit gehst du mit const ? Machst du einfach Funktionen wenn nötig oder gehst du das ganze Schwein und benutzt es überall? Stellen Sie sich beispielsweise einen einfachen Mutator vor, der einen einzigen booleschen Parameter verwendet:

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

Ist das eigentlich nützlich? Persönlich entscheide ich mich, es ausgiebig zu verwenden, einschließlich der Parameter, aber in diesem Fall frage ich mich, ob es sich lohnt?

Ich war auch überrascht zu erfahren, dass Sie const aus Parametern in einer Funktionsdeklaration weglassen können, aber in die Funktionsdefinition aufnehmen können, zB:

.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 etwas ungewöhnlich.




Kennwertparameter 'const' ist definitiv eine subjektive Sache.

Allerdings bevorzuge ich eigentlich, Wertparameter const zu markieren, genau wie in Ihrem Beispiel.

void func(const int n, const long l) { /* ... */ }

Der Wert für mich zeigt deutlich an, dass die Funktionsparameterwerte niemals von der Funktion geändert werden. Sie werden am Anfang den gleichen Wert haben wie am Ende. Für mich ist es Teil einer sehr funktionalen Programmiersprache.

Für eine kurze Funktion ist es wohl eine Verschwendung von Zeit / Raum, das "const" dort zu haben, da es normalerweise ziemlich offensichtlich ist, dass die Argumente nicht durch die Funktion modifiziert werden.

Für eine größere Funktion ist es jedoch eine Form der Implementierungsdokumentation, die vom Compiler erzwungen wird.

Ich kann sicher sein, dass ich, wenn ich Berechnungen mit 'n' und 'l' mache, diese Berechnung reformieren / verschieben kann, ohne Angst davor zu haben, ein anderes Ergebnis zu erhalten, weil ich einen Ort verpasst habe, an dem einer oder beide geändert wurden.

Da es sich um ein Implementierungsdetail handelt, müssen Sie die Wertparameter const nicht im Header deklarieren, so wie Sie die Funktionsparameter nicht mit denselben Namen deklarieren müssen, die die Implementierung verwendet.




Die folgenden zwei Zeilen sind funktional äquivalent:

int foo (int a);
int foo (const int a);

Offensichtlich wirst du a im Körper von foo nicht modifizieren können, wenn es auf die zweite Art definiert ist, aber es gibt keinen Unterschied von außen.

Wo const wirklich nützlich ist, ist mit Referenz-oder Zeiger-Parameter:

int foo (const BigStruct &a);
int foo (const BigStruct *a);

Was das sagt, ist, dass foo einen großen Parameter annehmen kann, vielleicht eine Datenstruktur, die Gigabytes groß ist, ohne sie zu kopieren. Außerdem sagt es dem Anrufer: "Foo wird den Inhalt dieses Parameters nicht ändern." Durch die Übergabe einer Konst-Referenz kann der Compiler bestimmte Leistungsentscheidungen treffen.

*: Es sei denn, es wirft die Const-Ness weg, aber das ist ein weiterer Post.




Ah, ein harter. Auf der einen Seite ist eine Deklaration ein Vertrag und es macht wirklich keinen Sinn, ein const Argument nach Wert zu übergeben. Auf der anderen Seite, wenn Sie die Funktionsimplementierung betrachten, geben Sie dem Compiler mehr Möglichkeiten, um zu optimieren, wenn Sie eine Argumentkonstante deklarieren.




Ich verwende const nicht für Werte-übergebene Parameter. Dem Aufrufer ist es egal, ob Sie den Parameter ändern oder nicht, es handelt sich um ein Implementierungsdetail.

Es ist wirklich wichtig, Methoden als const zu markieren, wenn sie ihre Instanz nicht modifizieren. Tun Sie das so, wie Sie gehen, denn sonst könnten Sie entweder eine Menge const_cast <> erhalten, oder Sie könnten feststellen, dass das Markieren einer Methode const eine Menge Code erfordert, weil sie andere Methoden aufruft, die mit const gekennzeichnet sein sollten.

Ich neige auch dazu, lokale vars const zu markieren, wenn ich sie nicht modifizieren muss. Ich glaube, dass es den Code leichter verständlich macht, indem man die "beweglichen Teile" leichter identifizieren kann.




Es gibt eine gute Diskussion zu diesem Thema in den alten "Guru of the Week" -Artikeln über comp.lang.c ++, die here moderiert here .

Der entsprechende GOTW-Artikel ist hier auf Herb Sutters Website verfügbar.




Wenn Sie die Operatoren ->* oder .* Verwenden, ist dies ein Muss.

Es verhindert, dass Sie etwas wie schreiben

void foo(Bar *p) { if (++p->*member > 0) { ... } }

was ich jetzt fast gemacht habe, und was wahrscheinlich nicht das tut, was Sie vorhaben.

Was ich sagen wollte war

void foo(Bar *p) { if (++(p->*member) > 0) { ... } }

und wenn ich eine const zwischen Bar * und p hätte, hätte mir der Compiler das gesagt.




All the consts in your examples have no purpose. C++ is pass-by-value by default, so the function gets copies of those ints and booleans. Even if the function does modify them, the caller's copy is not affected.

So I'd avoid extra consts because

  • They're redudant
  • They clutter up the text
  • They prevent me from changing the passed in value in cases where it might be useful or efficient.



Ich benutze const, wo ich kann. Const für Parameter bedeutet, dass sie ihren Wert nicht ändern sollten. Dies ist besonders wertvoll, wenn Sie durch Verweis gehen. const for function erklärt, dass die Funktion die Klassenmitglieder nicht ändern soll.




Being a VB.NET programmer that needs to use a C++ program with 50+ exposed functions, and a .h file that sporadically uses the const qualifier, it is difficult to know when to access a variable using ByRef or ByVal.

Of course the program tells you by generating an exception error on the line where you made the mistake, but then you need to guess which of the 2-10 parameters is wrong.

So now I have the distasteful task of trying to convince a developer that they should really define their variables (in the .h file) in a manner that allows an automated method of creating all of the VB.NET function definitions easily. They will then smugly say, "read the ... documentation."

I have written an awk script that parses a .h file, and creates all of the Declare Function commands, but without an indicator as to which variables are R/O vs R/W, it only does half the job.

BEARBEITEN:

At the encouragement of another user I am adding the following;

Here is an example of a (IMO) poorly formed .h entry;

typedef int (EE_STDCALL *Do_SomethingPtr)( int smfID, const char* cursor_name, const char* sql );

The resultant VB from my script;

    Declare Function Do_Something Lib "SomeOther.DLL" (ByRef smfID As Integer, ByVal cursor_name As String, ByVal sql As String) As Integer

Note the missing "const" on the first parameter. Without it, a program (or another developer) has no Idea the 1st parameter should be passed "ByVal." By adding the "const" it makes the .h file self documenting so that developers using other languages can easily write working code.




Ich würde const nicht auf Parameter wie diese setzen - jeder weiß bereits, dass ein Boolescher Wert (im Gegensatz zu einem booleschen &) konstant ist, also fügt das Hinzufügen von Werten die Leute dazu an zu denken "Warte, was?" oder sogar, dass Sie den Parameter als Referenz übergeben.




Const-Parameter sind 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, muss sichergestellt werden, dass die im Parameter verwendete Variable nicht im Rumpf der Funktion geändert wird. Warum sollte jemand einen By-Value-Parameter als Konstante definieren? :-)




const sollte der Standard in C ++ sein. So was :

int i = 5 ; // i is a constant

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






There's really no reason to make a value-parameter "const" as the function can only modify a copy of the variable anyway.

The reason to use "const" is if you're passing something bigger (eg a struct with lots of members) by reference, in which case it ensures that the function can't modify it; or rather, the compiler will complain if you try to modify it in the conventional way. It prevents it from being accidentally modified.