[C/C++] const auf integrale typen in einer Funktion sinnvoll?



  • Hallo zusammen,

    ich überfliege gerade Sourcen und bin auf folgende Konstruktion gestoßen.

    void funktion(const int a, const bool b)
    {
       // ...
    }
    

    Ist das sinvoll? Ok, wenn es ein call by reference wäre würde ich das verstehen. Aber bei call by value? 😕

    Kann mich jemand erleuchten?

    Gruß
    Tobi



  • Zu Dokumentationszwecken (dann weiß man beim Lesen der Funktion direkt Bescheid, dass diese Werte konstant sind)?



  • dort const halte ich für quatsch. ob ich später mal doch a ändern mag, ist mein geheimnis und hat in der schnittstelle nichts zu suchen.



  • Danke euch zwei für die Antwort...
    Ihr habt mich in meiner Denkweise bestätigt.



  • 'const' garantiert nicht, dass die variable in einem read-only bereich abgelegt wird, andererseits erlaubt 'const' dem compiler gewisse optimierungen. eigentlich isses immer schwer einzuschätzen, ob 'const' irgendwo sinnvoll ist oder nicht.
    http://www.c2.com/cgi/wiki?ConstIsaVirus
    🙂



  • Das hat der Programmierer dort wohl reingeschrieben weil er a nicht ändern will. Leider ist es nicht möglich dieses const vor der Öffentlichkeit zu verbergen, weshalb es normal nicht verwendet wird.



  • ;fricky schrieb:

    'const' garantiert nicht, dass die variable in einem read-only bereich abgelegt wird, andererseits erlaubt 'const' dem compiler gewisse optimierungen. eigentlich isses immer schwer einzuschätzen, ob 'const' irgendwo sinnvoll ist oder nicht.
    http://www.c2.com/cgi/wiki?ConstIsaVirus
    🙂

    Danke für den link ;fricky. Interssante Lektüre...



  • ;fricky schrieb:

    'const' garantiert nicht, dass die variable in einem read-only bereich abgelegt wird, andererseits erlaubt 'const' dem compiler gewisse optimierungen. eigentlich isses immer schwer einzuschätzen, ob 'const' irgendwo sinnvoll ist oder nicht.
    http://www.c2.com/cgi/wiki?ConstIsaVirus
    🙂

    Wo liegt der Sinn in dem Artikel? Offensichtlich liegt das Problem bei ihm und nicht an "const", er kritisiert ja nicht einmal "const", sondern dass er und seine Kollegen nicht alles strikt als const deklariert haben. Bei mir ist es nie der Fall, dass ich const hinzufügen muss, nur wegnehmen, weil sich herausstellt, dass ich einen Parameter doch verändere.

    Auch wie er direkt mutable erwähnt um const auszuhebeln zeigt, dass er wild am herumhacken ist. Ok, dann wundert es mich doch nicht mehr, dass du den Link gepostet hast.



  • Ich habe nie den Sinn von cost-correctnes verstanden. Fast immer ist mir einfach egal ob etwas veraendert wird und das wenig wo es nicht egal ist, mache ich das Design so, dass eine Veraenderung in Ordnung ist.

    Aber ich denke const wird in C++ gebraucht, wegen dem ganzen Referenzen und das man sich nie sicher ist, ob eine Variable eine Referenz ist oder nicht. In C ist alles entweder ein Wert oder ein Zeiger, so ist ein mutable Objekt immer explizit, ebenso wie in anderen Sprachen (Python, Ruby, Php, Java, C#....).

    Also als Beispiel, in Java bin ich mir immer zu 100% sicher, dass Data ein Mutable Objekt ist und dass eine Aenderung auf alle Referenzen wirkt. Auch bei setData() weis ich, dass newdata immer Veraenderbar ist.

    Data data = foo.getData();
    data.setXxxx("New Value");
    
    // oder anders:
    foo.setData(newdata);
    

    In C ist es aehnlich explizit.

    Data data = getData(foo); // data ist eine Kopie
    setXxxx(data, "New Value");
    
    Data* data = getData(foo); // data ist ein Zeiger
    setXxxx(*data, "New Value"); // das Deferenzieren macht es explizit
    
    // oder anders:
    setData(*foo, newdata); // wieder eine Deferenzierung, also explizit
    

    In C++ sind Referenzen gut versteckt und es faengt das Raten an, gibt getData() eine Kopie oder eine Referenz zurueck? Oder bei setData(), kann setData() mein newdata veraendern, oder nicht?

    Data data = foo.getData();
    data.setXxxx("New Value");
    
    // oder anders:
    foo.setData(newdata);
    


  • Tippgeber schrieb:

    ;fricky schrieb:

    'const' garantiert nicht, dass die variable in einem read-only bereich abgelegt wird, andererseits erlaubt 'const' dem compiler gewisse optimierungen. eigentlich isses immer schwer einzuschätzen, ob 'const' irgendwo sinnvoll ist oder nicht.
    http://www.c2.com/cgi/wiki?ConstIsaVirus
    🙂

    Wo liegt der Sinn in dem Artikel? Offensichtlich liegt das Problem bei ihm und nicht an "const", er kritisiert ja nicht einmal "const", sondern dass er und seine Kollegen nicht alles strikt als const deklariert haben.

    nö, er findet's doof, dass sich 'const' propagiert, so dass man einiges von seinem code umstellen muss, wenn man einmal mit 'const' angefangen hat. eine möglichkeit wäre: http://www.c2.com/cgi/wiki?AvoidConstCompletely
    aber ich meine nicht, dass 'const' grundsätzlich sinnlos ist, denn es hilft dem compiler besser zu optimieren, so wie 'restrict' z.b.
    🙂



  • ;fricky schrieb:

    aber ich meine nicht, dass 'const' grundsätzlich sinnlos ist, denn es hilft dem compiler besser zu optimieren, so wie 'restrict' z.b.
    🙂

    Lies mal GotW #81.

    const ist für sicherheit, nicht performance da. Wirklichen Einfluss auf die Performance hat const nur da man sich durch const defensive Kopien spart.



  • DEvent schrieb:

    Also als Beispiel, in Java bin ich mir immer zu 100% sicher, dass Data ein Mutable Objekt ist und dass eine Aenderung auf alle Referenzen wirkt. Auch bei setData() weis ich, dass newdata immer Veraenderbar ist.

    In Java gibt es const auf Klassen Ebene -> mutable und immutable Klassen.

    In C++ kannst du das für einzelne Objekte sagen. Und mehr noch, du kannst es für views auf objekte sagen. Du kannst ein non-const Objekt weitergeben mit einem const-view (sprich const referenz) und hast dadurch halt eine viel bessere kontrolle.

    In Java sind alle Objekte einer Klasse entweder const oder alle sind nicht const.

    In C++ sind Referenzen gut versteckt und es faengt das Raten an, gibt getData() eine Kopie oder eine Referenz zurueck? Oder bei setData(), kann setData() mein newdata veraendern, oder nicht?

    Nein.
    Selbes Problem in Java.
    gibt getData eine referenz oder eine kopie zurück. Das ist überall ein Fall für die Doku.



  • [quote="Shade Of Mine"
    const ist für sicherheit, nicht performance da.
    [/quote]
    für alles, typsicherheit, performance, bessere lesbarkeit des codes. nur nicht, um effektiv schreibzugriffe zu verhindern.
    🙂



  • Shade Of Mine schrieb:

    DEvent schrieb:

    Also als Beispiel, in Java bin ich mir immer zu 100% sicher, dass Data ein Mutable Objekt ist und dass eine Aenderung auf alle Referenzen wirkt. Auch bei setData() weis ich, dass newdata immer Veraenderbar ist.

    In Java gibt es const auf Klassen Ebene -> mutable und immutable Klassen.

    In C++ kannst du das für einzelne Objekte sagen. Und mehr noch, du kannst es für views auf objekte sagen. Du kannst ein non-const Objekt weitergeben mit einem const-view (sprich const referenz) und hast dadurch halt eine viel bessere kontrolle.

    In Java sind alle Objekte einer Klasse entweder const oder alle sind nicht const.

    Das gleiche kannst du auch in C++ machen, mutable/immutable Klassen, das ist eine Frage des Designs. Ob man sowas wirklich auf Objekt-Ebene braucht, laesst sich streiten. Ich wollte andeuten, dass man es in C++ braucht, weil eben die Referenzen implizit sind (eine Kopie und eine Referenz sehen und verhalten sich gleich, bis auf den Unterschied das man eine Referenz veraendern kann). Deswegen das const in C++, damit man eben eine Referenz nicht aus versehen veraendern kann.

    Shade Of Mine schrieb:

    In C++ sind Referenzen gut versteckt und es faengt das Raten an, gibt getData() eine Kopie oder eine Referenz zurueck? Oder bei setData(), kann setData() mein newdata veraendern, oder nicht?

    Nein.
    Selbes Problem in Java.
    gibt getData eine referenz oder eine kopie zurück. Das ist überall ein Fall für die Doku.

    Bis auf den Fall wo man eben die Doku nicht braucht, weil es ein Sprach-Konzept ist, dass alles Referenzen sind. Oder ein Sprach-Konzept, dass eine Kopie und eine Referenz sich explit unterscheiden (in C). Allein in C++ ist es ein Fall fuer die Doku und auch die reicht wohl nicht aus um Fehler mit Referenzen zu vermeiden, deswegen das const-Konzept in C++.



  • In C++ sind Referenzen gut versteckt und es faengt das Raten an, gibt getData() eine Kopie oder eine Referenz zurueck? Oder bei setData(), kann setData() mein newdata veraendern, oder nicht?

    Nein.
    Selbes Problem in Java.
    gibt getData eine referenz oder eine kopie zurück. Das ist überall ein Fall für die Doku.[/quote]
    Einen kleinen Einwand habe ich. Bitte keinen FlameWar!

    Java bietet hierzu ein Interface namens Cloneable. Implementiert eine Klasse diese Interface, muss diese die Methode clone() in der Klasse umsetzen. Das Resultat muss eine neue Instanz der Klasse sein. Zudem sollen die Methoden hashCode, equals, ... neu definiert werden. Da ansonsten ein Vergleich der Kopien False ergeben würde. Für weitere Fälle besitzt die SE entsprechende Interfaces, was zu einer klaren Regelung führt.

    Beipsiel:

    public class Abc implements Cloneable {
    
      // ein muss
      public Object clone() {
         // TODO
      }
    
      // soll
      public boolean equal(Object o) {
    ....
    }
    


  • volkard schrieb:

    dort const halte ich für quatsch. ob ich später mal doch a ändern mag, ist mein geheimnis und hat in der schnittstelle nichts zu suchen.

    War da nicht irgend was, dass void foo(int a); und void foo(int const a); die gleiche Funktion sind? Ich bin mir da nicht hunderprozentig sicher, aber zumindest bei einem kurzen Test beim GCC scheint es so zu sein und ich wüsste auch nichts, was dagegen sprechen sollte.

    Demnach kann man das Interface ohne const anbieten (da bringt das const ja nicht viel) und in der Implementierung dann const verwenden.



  • rüdiger schrieb:

    War da nicht irgend was, dass void foo(int a); und void foo(int const a); die gleiche Funktion sind?

    So ist es. void foo() und const void foo() allerdings nicht - obwohl const hier noch sinnloser ist.

    Top-level cv-Qualifikationen von Funktionsparametern sind nicht Teil des Funktionstyps.



  • DEvent schrieb:

    Das gleiche kannst du auch in C++ machen, mutable/immutable Klassen, das ist eine Frage des Designs. Ob man sowas wirklich auf Objekt-Ebene braucht, laesst sich streiten. Ich wollte andeuten, dass man es in C++ braucht, weil eben die Referenzen implizit sind (eine Kopie und eine Referenz sehen und verhalten sich gleich, bis auf den Unterschied das man eine Referenz veraendern kann). Deswegen das const in C++, damit man eben eine Referenz nicht aus versehen veraendern kann.

    In Java hast du nur Referenzen die ganze Zeit. Es ist das exakt selbe Konzept. Ob ich jetzt eine Kopie direkt habe (C++ by value) oder aber eine referenz auf eine Kopie (Java defensive Kopie) ist vollkommen gleich.

    Du brauchst const in C++ nicht mehr als du es in Java brauchst. Man kann mit Kopien und immutable Klassen gut arbeiten. const bietet eben den Vorteil ohne kopien auszukommen und hilft dem programmierer beim fehler vermeiden.

    Bis auf den Fall wo man eben die Doku nicht braucht, weil es ein Sprach-Konzept ist, dass alles Referenzen sind. Oder ein Sprach-Konzept, dass eine Kopie und eine Referenz sich explit unterscheiden (in C). Allein in C++ ist es ein Fall fuer die Doku und auch die reicht wohl nicht aus um Fehler mit Referenzen zu vermeiden, deswegen das const-Konzept in C++.

    Dann kannst du mir ja erklären ob ich obj hier ändere:

    Data d=obj.getData();
    d.setValue("foo");
    

    Hat sich jetzt obj geändert oder nicht?

    Du weisst es nicht, niemand weiss es. Hier braucht man eine Doku. Lustigerweise ist C++ hier doch klarer 😉

    Data d = obj.getData();
    d.setValue("foo");
    
    //versus
    Data& d = obj.getData();
    d.setValue("foo");
    

    Dieses Problem hat man in allen Sprachen wo es referenzen gibt.



  • Tobias Gerg schrieb:

    Ist das sinvoll? Ok, wenn es ein call by reference wäre würde ich das verstehen. Aber bei call by value? 😕

    Ich finde es nicht sinnvoll, da das const dort keine wirkliche Aussagekraft besitzt und eher die Schnittstelle mit unnötigen Informationen verwässert. Eine Kopie des Objekts kann man intern genauso anlegen, wieso soll es der Funktion nicht erlaubt sein, gleich den kopierten Parameter zu ändern?

    DEvent schrieb:

    Ich habe nie den Sinn von cost-correctnes verstanden. Fast immer ist mir einfach egal ob etwas veraendert wird und das wenig wo es nicht egal ist, mache ich das Design so, dass eine Veraenderung in Ordnung ist.

    Const-Correctness halte ich für ein sehr nützliches Feature. Es erlaubt mir, an der Schnittstelle schnell zu erkennen, ob etwas von einer Funktion verändert wird oder nicht. Selbst wenn man dieses Sprachmittel nicht unbedingt braucht (z.B. Java hat ja kein const in dem Sinne), hilft mir das Schlüsselwort, um schneller Fehler aufzudecken und Aufgaben besser zu formulieren (reicht Lesezugriff für jene Operation?).

    DEvent schrieb:

    Aber ich denke const wird in C++ gebraucht, wegen dem ganzen Referenzen und das man sich nie sicher ist, ob eine Variable eine Referenz ist oder nicht.

    const ist nicht speziell auf Referenzen ausgelegt, obwohl Const-Referenzen eine gewisse Spezialbehandlung bekommen (Temporaries). Wie meinst du "dass man sich nie sicher ist, ob eine Variable eine Referenz ist oder nicht?" Das sieht man normalerweise an der Deklaration, die in den meisten Fällen recht nahe beim darauf zugreifenden Code liegt.

    DEvent schrieb:

    Bis auf den Fall wo man eben die Doku nicht braucht, weil es ein Sprach-Konzept ist, dass alles Referenzen sind.

    Shade of Mine meinte es wohl eher semantisch; also dass eine Referenz auf dasselbe oder ein neues, kopiertes Objekt zurückgegeben werden kann. Das weiss man bei Java tatsächlich nicht ohne Weiteres, in C++ ist bei einer Referenzrückgabe klar, dass kein neues Objekt erstellt wurde, weil ein Stack-Objekt nicht mehr gültig wäre und ein Heap-Objekt explizit freigegeben werden müsste - das macht man aber nie über eine Referenz, nur über Zeiger. Insofern kann man mit der Deklaration schon einiges mitteilen.

    Hmm, ich frage mich, wie lange es wohl geht, bis jemand beginnt, mit const_cast gegen const zu argumentieren. 😉



  • Nexus schrieb:

    Hmm, ich frage mich, wie lange es wohl geht, bis jemand beginnt, mit const_cast gegen const zu argumentieren.

    dafür reicht schon der normale cast mit den klammern. aber egal, ein 'const' objekt und 'ent-consten' ist wohl in jedem fall undefiniert.
    🙂


Anmelden zum Antworten