2009-11-12 3 views
24

Ich weiß, es gibt wenig Frage über const Korrektheit, wo es heißt, dass die Deklaration einer Funktion und ihre Definition für Wertparameter nicht übereinstimmen müssen. Dies liegt daran, dass die Konsistenz eines Wertparameters nur in der Funktion von Bedeutung ist. Das ist in Ordnung:Const Korrektheit für Wert-Parameter

// header 
int func(int i); 

// cpp 
int func(const int i) { 
    return i; 
} 

Ist das wirklich eine Best Practice? Weil ich noch nie jemanden gesehen habe. Ich habe dieses Zitat gesehen (nicht sicher von der Quelle) an anderen Orten hat diese diskutiert:

"In fact, to the compiler, the function signature is the same whether you include this const in front of a value parameter or not."

"Avoid const pass-by-value parameters in function declarations. Still make the parameter const in the same function's definition if it won't be modified."

Der zweite Absatz sagt nicht die const in der Erklärung setzen. Ich gehe davon aus, dass die Konstanz eines Wertparameters als Teil einer Schnittstellendefinition bedeutungslos ist. Es ist ein Implementierungsdetail.

Aufgrund dieser Empfehlung wird es auch für die Zeigerwerte von Zeigerparametern empfohlen? (Es ist auf einem Referenz-Parameter bedeutungslos, da Sie nicht eine Referenz zuweisen können.)

// header 
int func1(int* i); 
int func2(int* i); 

// cpp 
int func1(int* i) { 
    int x = 0; 

    *i = 3; // compiles without error 
    i = &x; // compiles without error 

    return *i; 
} 
int func2(int* const i) { 
    int x = 0; 

    *i = 3; // compiles without error 
    i = &x; // compile error 

    return *i; 
} 

Zusammenfassung: machen Wertparameter nützlich ist, einige Logikfehler zu fangen. Ist es eine gute Praxis? Gehen Sie zu dem Extrem, das const aus der Header-Datei zu lassen? Ist es genauso nützlich, Zeigerwerte konstant zu halten? Warum oder warum nicht?

Einige Referenzen:

C++ const keyword - use liberally? Use of 'const' for function parameters

Ein Beispiel, wenn konst Wertparameter sind nützlich:

bool are_ints_equal(const int i, const int j) { 
    if (i = j) { // without the consts this would compile without error 
     return true; 
    } else { 
     return false; 
    } 
    // return i = j; // I know it can be shortened 
} 
+0

Es fängt die „if (i = j)“ Fehler in diesem Fall muss aber nicht alle solche Fehler zu fangen, also würde ich mich über diese spezielle Logik nicht zu sehr aufregen (da Sie mit Variablen denselben Fehler machen können). Sogar ohne const sollte dein Compiler dich davor warnen, wenn du sagst, dass du Warnungen willst. – nobar

+0

Der Punkt, an dem man durch 'if (i = j)' erregt wird, ist zu erkennen, dass konstante Werte nicht nur Flusen sind. Michael Burrs Beispiel ist sogar besser als dieses. – jmucchiello

+2

In einer Situation, wo Sie die Funktionsparameter nicht ändern, sollten Sie sie const, weil A) es sicherer ist, B) es selbst-Dokumentieren, und C) es ist mehr Debug-freundlich. Außerdem sollten der Prototyp und der Header als const gekennzeichnet sein. Es ist verwirrend, wenn nur die im Header der Funktion getan. Das Argument zum Erstellen einer temporären Variablen innerhalb der Funktion ist eine Situation, in der Sie wahrscheinlich den/die Parameter const nicht deklarieren müssen. Das sind meine 2 Pfennige. –

Antwort

7

Mein Nehmen auf sie:

Es ist keine schlechte Idee, aber das Problem ist gering und Ihre Energie könnte besser für andere Dinge ausgegeben werden.

In Ihrer Frage, sofern Sie ein gutes Beispiel dafür, wann es möglicherweise einen Fehler zu fangen, aber gelegentlich auch bis Sie am Ende so etwas wie dies zu tun:

void foo(const int count ...) 
{ 
    int temp = count; // can't modify count, so we need a copy of it 
    ++temp; 

    /* ... */ 
} 

Die Vor- und Nachteile gering sind oder so.

+3

+1 für zu sagen, es ist keine schlechte Idee, und das Problem zu beachten ist gering. Aber bevor du den Parameter ins Innere kopierst, würde ich einfach das const entfernen (außer vielleicht, wenn du immer "count" kopierst, als Prinzip, nicht mit einem Parameter zu arbeiten, und nicht nur wegen der const, die dich verhindert) –

+8

Normalerweise wann Wenn Sie die Variable ändern, ändern Sie die semantische Bedeutung. Zum Beispiel: void foo (const int index0basiert) {const int index1based = index0based + 1;} Man könnte es einfach Index nennen und ändern, aber das ist viel klarer für den schlechten Wartungsprogrammer, der in 5 Jahren kommt. – Bill

+0

@ Bill, ausgezeichneter Punkt! –

9

ich viele Male gelesen habe, dass in einem Funktionswert Parameter machen Const ist eine schlechte Sache zu tun, weil es unnötig ist.

Allerdings finde ich es gelegentlich hilfreich für mich als Kontrolle, dass meine Implementierung etwas nicht tut, was ich nicht vorhabe (wie im Beispiel am Ende Ihrer Frage).

Also, während es nicht den Wert für den Aufrufer hinzufügen kann, fügt es manchmal ein kleines bisschen von Wert als Implementierer, und es nimmt nichts weg von dem Aufrufer. Also sehe ich keinen Schaden damit.

Zum Beispiel kann ich eine C-Funktion, die ein paar Zeiger auf einen Puffer - ein Zeiger auf den Start und einen Zeiger auf das Ende dauert. Ich werde Daten in den Puffer legen, aber sicherstellen, dass ich das Ende nicht überlaufe. Also in der Funktion gibt es Code, der einen Zeiger inkrementieren wird, während ich ihm Daten hinzufüge. Der Zeiger auf das Ende des Puffers ein const Parameter wird dafür sorgen, dass ich nicht einen Fehler, der versehentlich die Endgrenze Zeiger anstelle der Zeiger, die ich wirklich inkrementieren sollte erhöht.

So eine FillArray Funktion mit einer Signatur wie folgt aus:

size_t fillArray(data_t* pStart, data_t* const pEnd); 

wird mich nicht versehentlich pEnd erhöht wird, wenn ich meine wirklich pStart zu erhöhen. Es ist keine große Sache, aber ich bin mir ziemlich sicher, dass jeder, der für einen bestimmten Zeitraum in C programmiert hat, über einen solchen Fehler hinweggelaufen ist.

+0

Ausgezeichnet. Ich suchte nach einem guten Beispiel für einen konstanten Zeigerwert. – jmucchiello

1

Leider unterscheiden einige Compiler (ich betrachte Sie, Sun CC!) Falsch zwischen const erklärten und nicht deklarierten Argumenten, und Sie können Fehler über undefinierte Funktionen erhalten.

-2

Ich mag const Korrektheit für Situationen wie diese:
void foo(const Bar &b) //I know b cannot be changed
{
//do something with b
}

Das bin ich b lässt verwenden, ohne Angst, sie zu ändern, aber ich habe nicht die Kosten eines Copykonstruktor zu bezahlen.

+8

Wir sprechen nicht über Referenzparameter. Nur Wertparameter – jmucchiello

0

Ich denke, das ist abhängig von Ihrem persönlichen Stil.

Es addiert oder subtrahiert nicht, was Clients an Ihre Funktion übergeben können. Im Wesentlichen ist es wie eine Kompilierungszeit Behauptung. Wenn es dir hilft zu wissen, dass sich der Wert nicht ändert, mach weiter und tu es, aber ich sehe keinen großen Grund dafür, dass andere es tun.

Ein Grund, warum ich das vielleicht nicht tue, ist, dass die Const-ness des Value-Parameters ein Implementierungsdetail ist, über das Ihre Kunden nichts wissen müssen. Wenn Sie Ihre Funktion später (absichtlich) so ändern, dass sie diesen Wert tatsächlich ändert, müssen Sie die Signatur Ihrer Funktion ändern, wodurch Ihre Clients gezwungen werden, sie neu zu kompilieren.

Das ist ähnlich, warum einige Leute empfehlen, keine öffentlichen virtuellen Methoden zu haben (die Funktionen virtual-ness ist ein Implementierungsdetail, das vor Clients verborgen werden sollte), aber ich bin nicht in diesem bestimmten Lager.

+2

Lesen Sie die Frage erneut. Die Headerdatei hat nicht die Konstante const, weil es dem Aufrufer egal ist, ob die Implementierung eine lokale Variable ändert. Hierbei handelt es sich ausschließlich darum, ob es sich auf der Implementierungsseite lohnt. – jmucchiello

0

Wenn ein const-Schlüsselwort vorhanden ist; es bedeutet, dass der Wert von 'i' (der Typ const) nicht geändert werden kann. Wenn der Wert von 'i' ist innerhalb foo Funktion Compiler geändert werden Fehler aus: "

Can not modify const object

Aber Ändern '* i' (dh * i = 3;) bedeutet, dass Sie nicht Wert ändern sich von 'i' aber Wert der Adresse, die von ‚i‘

Eigentlich zeigte, ist die konstante Funktion für große Objekte angemessen, die durch die Funktion nicht geändert werden sollen.

0

Wir alle von jemandem anderen C++ Code von Zeit zu Zeit zu entwirren haben. Und das der C++ - Code einer anderen Person ist per Definition ein komplettes Durcheinander: D.

Also das erste, was ich immer tun, um es zu entschlüsseln (lokale & globalen Datenfluss) ist const in jeder Variablendefinition gesetzt, bis Compiler beschwert. Das bedeutet auch, value arguments const zu qualifizieren, und es hilft wirklich, Variablen zu vermeiden, die in der Mitte der Funktion geändert wurden, ohne dass ich es merke ...

Also wirklich schätze ich, wenn dass jemand anderes const überall hat (einschließlich Wertparameter): D