Was ist der ganze Sinn von Konstanten? (const)



  • Fazit:
    const-correctness macht das C++ Typsystem noch strenger. Und je strenger die Typprüfung, desto mehr Fehler können bereits zur Compilezeit entdeckt werden. Jeder Fehler der zur Compilzeit gefunden wird, ist einer weniger nach dem zur Laufzeit gesucht werden muss.

    Von http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=constcor#Answ



  • okay ich verstehe. danke!

    es gibt halt den code aus dem buch c++ lernen und professionel anwenden:

    CD( const string& i="", const string& t="", long s = 0L)
         { 
            interpret = i;    title = t;    seconds = s;
         }
    

    da frag ich mich warum long s keine konstante ist, aber die beiden strings schon.

    ob ich jetzt da draus konstante mache (const long& s = 0L) oder von den strings wegmache, beides funktioniert. Warum hat nur das dritte argument keine konstante?



  • x schrieb:

    da frag ich mich warum long s keine konstante ist, aber die beiden strings schon.

    ob ich jetzt da draus konstante mache (const long& s = 0L) oder von den strings wegmache, beides funktioniert. Warum hat nur das dritte argument keine konstante?

    Was an diesem Code wichtig ist, ist die Tatsache, dass die Strings als Referenz übergeben werden. Das ist gut, denn dadurch müssen sie nicht kopiert werden. Wenn man sie nun *nicht* als 'const' übergeben würde, könnte man aber z.B. folgenden Code nicht schreiben:

    CD("hallo", "du", 0);
    

    Denn '"hallo"' und '"du"' sind *keine* Strings sondern 'char const*'. Diese können zwar implizit in Strings konvertiert werden, aber nur, wenn diese Strings konstant sind. Daher sind die String-Referenzen als 'const' übergeben. Der Long-Parameter hingegen nicht, denn dort ist es nutzlos: Das 'long' wird bei der Übergabe eh kopiert, d.h. selbst wenn man es in der Funktion verändert, wirkt sich dies nicht auf den übergebenen Wert auf: Er bleibt unverändert. Daher kann ich auch konstante Long-Werte an die Funktion übergeben, ohne den Parameter als 'const' deklariert zu haben.

    Hätte man stattdessen eine 'long'-Referenz übergeben, hätte man diese auch 'const' machen müssen, um Konstanten als Parameter verwenden zu können. Allerdings ist es relativ sinnlos, ein 'long' per Referenz zu übergeben, denn ein 'long' bei der Parameter-Übegabe zu kopieren, ist billig. Strings zu kopieren hingegen ist teuer (wobei ich mir nicht sicher bin, was C++ hier mit 'char const*' macht; es könnte sein, dass die trotzdem von 'string'-Konstruktor kopiert werden).



  • Wobei in dem Beispiel das eher so gemacht würde:

    CD(const std::string& interpret, const std::string& title, long playtime) : m_interpret(interpret), m_title(title), m_seconds(playtime)
    {
    }
    

    😉



  • hi! danke für die ausführliche Erklärung, danke für die mühe!

    "Allerdings ist es relativ sinnlos, ein 'long' per Referenz zu übergeben, denn ein 'long' bei der Parameter-Übegabe zu kopieren, ist billig."

    Ohne Referenz heisst aber schon dass man einmal auf s kopieren muss und dann nochmal auf seconds, oder? wenn die Objekte ganz viel erzeugt werden, wird das schon bemerklich sein? Oder optimiert das der Compiler weg?



  • @(D)Evil: Ja das mit Elementinitialisierer muss ich nochmal lesen. Ich lerne eben C++. Verwirrt mich alles bei sovielen Möglichkeiten.



  • x schrieb:

    hi! danke für die ausführliche Erklärung, danke für die mühe!

    "Allerdings ist es relativ sinnlos, ein 'long' per Referenz zu übergeben, denn ein 'long' bei der Parameter-Übegabe zu kopieren, ist billig."

    Ohne Referenz heisst aber schon dass man einmal auf s kopieren muss und dann nochmal auf seconds, oder?

    Ja, aber wenn Du es per Referenz übergibst, muss die Referenz auf dem Stack abgelegt werden, d.h. dadurch sparst Du nichts.

    Oder optimiert das der Compiler weg?

    Mit den entsprechenden Einstellungen optimiert der Compiler extrem viel weg; aber um dieses Kopieren wegzuoptimieren müsste der gesamte Methodenaufruf ge-inlined werden, eine andere Möglichkeit gibt es nicht. Allerdings klappt gerade Inlining sehr gut.



  • x schrieb:

    hi! danke für die ausführliche Erklärung, danke für die mühe!

    "Allerdings ist es relativ sinnlos, ein 'long' per Referenz zu übergeben, denn ein 'long' bei der Parameter-Übegabe zu kopieren, ist billig."

    Ohne Referenz heisst aber schon dass man einmal auf s kopieren muss und dann nochmal auf seconds, oder? wenn die Objekte ganz viel erzeugt werden, wird das schon bemerklich sein? Oder optimiert das der Compiler weg?

    Built-in Typen zu kopieren ist billig. Das ist eine CPU-Anweisung, die du ohnehin machen müsstest. Eine Referenz hätte in dem Fall nur einen zusätzlichen Overhead.



  • danke an rest

    (D)Evil schrieb:

    Wobei in dem Beispiel das eher so gemacht würde:

    CD(const std::string& interpret, const std::string& title, long playtime) : m_interpret(interpret), m_title(title), m_seconds(playtime)
    {
    }
    

    😉

    wo sind dann die vordefinierten werte? geht das so auch: ?

    CD(const std::string& interpret = "", const std::string& title = "", long playtime = 0L) : m_interpret(interpret), m_title(title), m_seconds(playtime)
    {
    }
    

    ich frage nur dumm. vielleicht gibt es einen grund warum du das weggemacht hast? performance?



  • hat er vermutlich nur übersehen. Geht natürlich auch so.

    btw. brecht bitte die Zeilen rechtzeitig um, ist ja schrecklich! 🙂

    (und denk nicht bei jeder Kleinigkeit an "Performance"!)


Anmelden zum Antworten