Konstaten wirklich invariabel?



  • Hallo

    Ich habe eine kurze Frage zu Konstanten

    const int i = 5;
    cout << "i hat der Wert: " << i << endl;
    

    Funktioniert. Augabe = 5.

    Mit einer erneuten Deklaration, gibt der Compiler einen Fehler aus.
    Soweit hab ich das verstanden.
    Jetzt ist meine Frage, ob eine Konstante überhaupt nicht verändert werdenn kann, oder, ob die Angabe "const" nur eine erneute Deklaration verbietet?

    Denn;

    const int i = 5;
    cout << "i hat der Wert: " << i + 2 << endl; 
    

    verändert die Konstante ja.

    Danke im voraus.
    Grüße

    korrigiert .



  • Füg darunter folgende Zeile ein:

    cout << i << endl;
    

    Dann siehst du das deine Aussage nicht stimmt. i Ändert sich da nicht.
    Aus i + 2 ensteht ein temporärer integer der dann an operator<< weitergegeben wird. (hier vermutlich in nem register - EDIT: Ne der compiler optimiert das vermutlich auch wiederum einfach weg zu ner konstante in dem Ausdruck. - Es ist sinnlos über so ein kleines Beispiel nachzudenken -.-).

    Und nein 'const' bedeutet nicht zwangsweise Konstant. Wegen const_cast
    Man kann constness weg casten und dann etwas zuweisen. Es gibt aber nie ein Grund dafür das zu tun.
    (Ich kenne ein Beispiel aus einem Buch, das einen legitimen Fall zeigen soll, ich glaube sogar das war von scott meyers, aber Ich befand dem nicht so)

    Ich bin mir nicht sicher, aber ich glaube dass das wegcasten von const in manchen Fällen sogar zu UB führt / verboten ist.
    (EDIT: Ich muss das nicht wissen, wenn man das eh nie tut :P)



  • @tryn4x

    verändert die Konstante ja.

    Nein!



  • Hallo.

    Alles klar und Dankeschön, war mein Fehler.



  • @5cript sagte in Konstaten wirklich invariabel?:

    Ich bin mir nicht sicher, aber ich glaube dass das wegcasten von const in manchen Fällen sogar zu UB führt / verboten ist.

    Der cast nicht, aber [dcl.type.cv]/4:

    Any attempt to modify a const object during its lifetime results in undefined behavior.



  • Nein, Konstanten sind nicht invariabel. Sie sind natürlich physikalisch änderbar. PCs bringen auch die Hardware mit, um die Konstante die du programmiert hast, wieder zu ändern. Sonst könntest du auch den ersten Wert der Konstante nicht festlegen. Konstanten sind lediglich auf einem gewissen Level der Abstraktion "konstant".

    Das gleiche trifft übrigens auch auf Programmcode zu. Innerhalb einer Executable betrachten wir Code normalerweise als konstant. Offensichtlich ist er das aber nicht, denn wir könnten sonst keinen neuen schreiben.


  • Mod

    @TGGC sagte in Konstaten wirklich invariabel?:

    Nein, Konstanten sind nicht invariabel. Sie sind natürlich physikalisch änderbar. PCs bringen auch die Hardware mit, um die Konstante die du programmiert hast, wieder zu ändern. Sonst könntest du auch den ersten Wert der Konstante nicht festlegen. Konstanten sind lediglich auf einem gewissen Level der Abstraktion "konstant".

    Das stimmt aber auch nur, solange sie physisch überhaupt existieren. Konstanten sind schließlich super Kandidaten für totale Wegoptimierung. Daher ist das auch undefiniertes Verhalten, eine Konstante über Hacks zu ändern, denn man kann das Programmverhalten dann in Angesicht von Optimierungen nicht mehr vorhersehen:

    	const int c = 3;
    	const int *cp = &c;
    	int * p = const_cast<int*>(cp);
    	*p = 4;
    	for (int i = 0; i < c; ++i)
    		cout << i;
    

    Da wurde vielleicht die Schleife 3x abgerollt. Oder das ganze Programm zu puts("012"); optimiert. Oder nichts davon. Oder ganz was anderes.



  • @5cript sagte in Konstaten wirklich invariabel?:

    Man kann constness weg casten und dann etwas zuweisen. Es gibt aber nie ein Grund dafür das zu tun.
    (Ich kenne ein Beispiel aus einem Buch, das einen legitimen Fall zeigen soll, ich glaube sogar das war von scott meyers, aber Ich befand dem nicht so)

    Ich bin mir ziemlich sicher, dass das nicht stimmt. Das Beispiel was du wahrscheinlich im Kopf hast, ist das hinzu casten von const, um eine gleichnamige const Funktion nutzen zu können und Codeverdopplung zu vermeiden.
    Ansonsten würde ich gerne genauer wissen, wo er das gesagt haben soll.


  • Mod

    @Jockelx sagte in Konstaten wirklich invariabel?:

    @5cript sagte in Konstaten wirklich invariabel?:

    Man kann constness weg casten und dann etwas zuweisen. Es gibt aber nie ein Grund dafür das zu tun.
    (Ich kenne ein Beispiel aus einem Buch, das einen legitimen Fall zeigen soll, ich glaube sogar das war von scott meyers, aber Ich befand dem nicht so)

    Ich bin mir ziemlich sicher, dass das nicht stimmt. Das Beispiel was du wahrscheinlich im Kopf hast, ist das hinzu casten von const, um eine gleichnamige const Funktion nutzen zu können und Codeverdopplung zu vermeiden.
    Ansonsten würde ich gerne genauer wissen, wo er das gesagt haben soll.

    Vielleicht ist es ein Cast von const char* nach char *, um ein Legacystringinterface zu benutzen. Die Umwandlung ist zwar bei den meisten Compilern auch heute noch implizit erlaubt, aber nach strenger ISO-Auslegung ist da eigentlich ein Cast nötig.

    Ist aber anstreitbar, ob das "legitim" ist. Das wäre schließlich ein Herumprogrammieren um einen Fehler in der Legacy-API und kein "echter" Fall wo man den Cast bräuchte, ohne dass ein Fehler vorliegt.



  • @SeppJ sagte in Konstaten wirklich invariabel?:

    Das stimmt aber auch nur, solange sie physisch überhaupt existieren. Konstanten sind schließlich super Kandidaten für totale Wegoptimierung. Daher ist das auch undefiniertes Verhalten, eine Konstante über Hacks zu ändern, denn man kann das Programmverhalten dann in Angesicht von Optimierungen nicht mehr vorhersehen:

    	const int c = 3;
    	const int *cp = &c;
    	int * p = const_cast<int*>(cp);
    	*p = 4;
    	for (int i = 0; i < c; ++i)
    		cout << i;
    

    Da wurde vielleicht die Schleife 3x abgerollt. Oder das ganze Programm zu puts("012"); optimiert. Oder nichts davon. Oder ganz was anderes.

    Wenn du mal noch eine Ebene weiter rausgehst, wirst du feststellen, das die Konstante trotzdem irgendwie abgespeichert wurde - also physisch existieren muss - wenn sie irgendwie benutzt werden soll. Also z.B. ist die "3" gespeichert indem dreimal der Code untereinander kopiert ist, grad kurz in Godbolt getestet:

            xor     esi, esi
            mov     edi, OFFSET FLAT:_ZSt4cout
            call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
            mov     esi, 1
            mov     edi, OFFSET FLAT:_ZSt4cout
            call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
            mov     esi, 2
            mov     edi, OFFSET FLAT:_ZSt4cout
            call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
    
    

    Und auch das ist nun lange nicht konstant, denn weitere Kopien einfügen/löschen ist hier sogar recht trivial. Das wird praktisch natürlich komplexer als in dem Beispiel, was aber an der theoretischen Aussage nichts ändert.



  • @Jockelx sagte in Konstaten wirklich invariabel?:

    Ich bin mir ziemlich sicher, dass das nicht stimmt. Das Beispiel was du wahrscheinlich im Kopf hast, ist das hinzu casten von const, um eine gleichnamige const Funktion nutzen zu können und Codeverdopplung zu vermeiden.

    Nein, es geht um das WEGcasten von const. Hier: https://stackoverflow.com/questions/123758/how-do-i-remove-code-duplication-between-similar-const-and-non-const-member-func



  • @wob Mmmh?
    Die non-const Funktion ruft die const Funktion auf. Der non-const wird also ein const hinzugefügt.
    (das ist übrigens das Beispiel was ich meinte)


  • Mod

    @TGGC sagte in Konstaten wirklich invariabel?:

    [...]

    Das ist dann aber eine ziemlich nutzlose Aussage.



  • @SeppJ Könnte man dann bald mit "ja, Computer sind programmierbar" zusammenfassen 😉



  • @Jockelx sagte in Konstaten wirklich invariabel?:

    @wob Mmmh?
    Die non-const Funktion ruft die const Funktion auf. Der non-const wird also ein const hinzugefügt.
    (das ist übrigens das Beispiel was ich meinte)

    Hm. Vielleicht verstehe ich dich nicht richtig.

       Z& Z(size_t index)
       {
          // One line. One ugly, ugly line - but just one line!
          return const_cast<Z&>( static_cast<const X&>(*this).Z(index) );
       }
    

    Hier wird doch eindeutig mit const_cast das const WEGgecastet, damit man die const-Funktion benutzen kann, um ein non-const-Ergebnis zu liefern.

    Edit: ah, ich glaube, ich verstehe, was du meinst. Du beziehst dich auf den zweiten Cast dort, der jetzt auch als durch std::as_const ersetzt werden könnte? Es ging mir um das "Man kann constness weg casten und dann etwas zuweisen. " worauf du "Ich bin mir ziemlich sicher, dass das nicht stimmt." sagtest. Ich sage: doch, man kann es wegcasten und dann was zuweisen (gut, nachdem in der Funktion das const erst hinzugecastet wurde, aber darauf bezog ich mich nicht)



  • @hustbaer sagte in Konstaten wirklich invariabel?:

    @SeppJ Könnte man dann bald mit "ja, Computer sind programmierbar" zusammenfassen 😉

    Richtig und daher existieren Konstanten eben nur auf einem gewissen Level der Abstraktion.

    @SeppJ sagte in Konstaten wirklich invariabel?:

    @TGGC sagte in Konstaten wirklich invariabel?:

    [...]

    Das ist dann aber eine ziemlich nutzlose Aussage.

    Kommt drauf an, warum man die Frage stellt. Die Antwort gibt ja nun mal die Realität wieder.



  • @wob
    Ja, okay, technisch hast du Recht. Ich habe mir das jetzt nicht genau angeschaut, weil ich den Tipp noch ganz gut im Gedächnis hatte und er x mal darauf hingewiesen hat, dass er immer nur mit non-const Dingen const Dinge macht.
    Und die Sichtweise hatte ich jetzt auch nur im Blick: mache etwas const und rufe damit const Funktionen auf. Niemals anders herum!
    Heisst: Füge const hinzu. Aber ja, technisch hast du Recht; das hinzugefügte const muss am Ende natürlich wieder entfernt werden.



  • @Jockelx sagte in Konstaten wirklich invariabel?:

    h den Tipp noch ganz gut im Gedächnis hatte und er x mal darauf hingewiesen hat, dass er immer nur mit non-const Dingen const Dinge macht.

    Ah das hatte ich dann falsch im Gedächtnis.
    Ich hab das noch nie gebraucht, weil ich noch nie ne Funktion in const und non const hatte die das gleiche macht. denk, vllt doch aber das waren one-liner.

    EDIT: Könnte das mal gemacht haben ohne drüber nachzudenken.
    Dass ich das Buch gelesen habe ist mindestens 8 Jahre her.



  • @TGGC
    Doch, Konstanten* sind invariabel. Denn Konstanten sind eine Abstraktion. Dass eine konkrete Umsetzung dieser Abstraktion dann oftmals nicht perfekt ist und trotzdem irgendwie eine Änderung zulässt, ist dann wieder was anderes.

    Und, wenn ich dich diesbezüglich richtig verstanden habe: Wie das Neuübersetzen eines (geänderten) Programms das Ändern einer Konstante darstellen soll, das müsstest du mir auch erstmal erklären. Nur weil ich etwas zerstören und dann in anderer Form neu erschaffen kann heisst das nicht dass ich es ändern kann. Weil das neue Ding nicht mehr die selbe Identität hat wie das alte.

    *: "Echte" Konstanten, so wie C++ static const int & Co.



  • Ob das was Anderes ist oder nicht, kommt ganz drauf an um was es geht.

    Ich sprach auch gar nicht davon, das Neuübersetzen eine Konstante ändert, sondern das es den Code ändert.



  • Ich finde die philosophisch anmutende Diskussion, ob Konstanten konstant oder nur abstrakt konstant sind, nicht sonderlich hilfreich.

    Der TE hat Probleme bei der sematischen Interpretation von i von i + 1. Er ist also noch etwas unerfahren in C++.

    Und nun sieht er, wie sich ein Forum darüber streitet, ob const int konstant ist oder nicht. Warum sollte er da nicht denken: "Wenn das Forum nicht weis, ob const int konstant ist oder nicht, warum sollte ich dann überhaupt const nutzen?"

    Und das würde dazu führen, dass der TE ein meines Erachtens wichtiges Hilfsmittel nicht nutzt. Ein Hilfsmittel welches ausdrückt: Lieber Entwickler es ist von mir nicht angedacht die Variable/Parameter zu ändern. Solltest du nach Seiteneffekten wg. Parametern suchen, so habe ich den Parameter nicht verändert...

    PS:
    Ironischerweise hat in der Embedded Welt const irgentwie seine ursprüngliche Bedeutung verloren. Bei einigen MCU's landen static const im FLASH ROM. Bei gesetzten Lock Bits und vergossenem Programmierport kann man danach gar nichts mehr ändern.

    https://community.st.com/s/question/0D50X00009XkY1qSAF/store-constant-variables-in-flash
    https://stackoverflow.com/questions/54532302/static-const-vs-const-declaration-performance-difference-on-uc

    Das Ganze ist offenbar so verbreitet, das bei einigen Entwickler der Gedanke "const = ROM" aufkam und dadurch vermutlich Mempory Specifier wie PROGMEM eingeführt wurden.

    https://www.nongnu.org/avr-libc/user-manual/pgmspace.html


Anmelden zum Antworten