Verwirrende Ausgabe


  • Mod

    Bei jedem Aufruf von deiner Ausgabefunktion wird das vorherige Ergebnis überschrieben (man sagt: Deine Funktion hat Nebeneffekte). Weiterhin ist nicht festgelegt, in welcher Reihenfolge die Ausgabefunktionen in einem Ausdruck wie

    std::cout << datum1.asString() << " ist nicht dasselbe Datum wie " << datum2.asString() << std::endl;
    

    abgearbeitet werden, aber es ist garantiert, dass sie beide abgearbeitet werden, bevor die eigentliche Ausgabe geschieht. Das heißt, hier wird 2x das gleiche Datum ausgegeben (aber es ist unspezifiziert, welches von beiden). Nach dem if-Konstrukt wird wieder deine Ausgabefunktion aufgerufen, die wieder das alte Ergebnis überschreibt:

    std::cout << datum2.asString() << std::endl;
    

    Dies geschieht garantiert vor der Ausgabe, folglich wird korrekt datum2 ausgegeben.

    Merke: Funktionen mit Nebeneffekten in unspezifizierter Reihenfolge aufzurufen ist ganz, ganz böse! Daher ist die Konstruktion mit der Referenz auf statischen Speicher auch ziemlich unsinnig, wie ich schon erwähnte. Wie soll man diese Funktion jemals intuitiv benutzen können, wenn man auf solche Nebeneffekte achten muss? Ganz schlechter Lehrer 👎 .



  • Okay, dann wäre es nun geklärt. Ich erwähne jetzt besser mal nicht die Quelle, sonst gibt es hier nur noch Hateposts (es ist nicht Jürgen Wolf, soviel sei gesagt)... Mir gefiel die Lösung mit einem String als Rückgabewert sowieso von Anfang an besser.
    Danke nochmal an SeppJ und alle anderen!

    Gruß



  • Anonymus42 schrieb:

    Mir gefiel die Lösung mit einem String als Rückgabewert sowieso von Anfang an besser.

    const string& asString() const;
    

    Diese Signatur ist gar nicht mal so schlecht. Wenn mehrmals asString aufgerufen wird möchte man das Resultat irgendwie merken.

    mutable std::string as_string_cache;
    bool value_changed;
    
    const string& asString() const {
      if (value_changed)
        as_string_cache = ...
      return as_string_cache;
    }
    

    Lässt man Multithreading ausser Acht gibt es an diesem Code nichts auszusetzen. Das wäre eine gute Möglichkeit gewesen um das Schlüsselwort mutable einzuführen. Das mit static zu lösen ist hingegen Quatsch.



  • SeppJ schrieb:

    Weiterhin ist nicht festgelegt, in welcher Reihenfolge die Ausgabefunktionen in einem Ausdruck wie

    std::cout << datum1.asString() << " ist nicht dasselbe Datum wie " << datum2.asString() << std::endl;
    

    abgearbeitet werden, aber es ist garantiert, dass sie beide abgearbeitet werden, bevor die eigentliche Ausgabe geschieht.

    Das bezweifle ich.


  • Mod

    Bashar schrieb:

    SeppJ schrieb:

    Weiterhin ist nicht festgelegt, in welcher Reihenfolge die Ausgabefunktionen in einem Ausdruck wie

    std::cout << datum1.asString() << " ist nicht dasselbe Datum wie " << datum2.asString() << std::endl;
    

    abgearbeitet werden, aber es ist garantiert, dass sie beide abgearbeitet werden, bevor die eigentliche Ausgabe geschieht.

    Das bezweifle ich.

    Was genau?

    Die Undefiniertheit der Reihenfolge?
    Die Abarbeitung jeweils vor der Ausgabe?

    Ahh, ich glaube ich weiß was du meinst: Das beide abgearbeitet werden, bevor die Gesamtausgabe erfolgt? Nein, so hatte ich das auch nicht gemeint. Besser formuliert:
    ...aber es ist garantiert, dass sie jeweils beide abgearbeitet werden, bevor die eigentliche Ausgabe geschieht, wobei durchaus auch beide vorher abgearbeitet werden dürfen (aber nicht müssen).

    Ziemlich umständlich formuliert, aber dafür verwechselungssicher.



  • SeppJ schrieb:

    Bashar schrieb:

    SeppJ schrieb:

    Weiterhin ist nicht festgelegt, in welcher Reihenfolge die Ausgabefunktionen in einem Ausdruck wie

    std::cout << datum1.asString() << " ist nicht dasselbe Datum wie " << datum2.asString() << std::endl;
    

    abgearbeitet werden, aber es ist garantiert, dass sie beide abgearbeitet werden, bevor die eigentliche Ausgabe geschieht.

    Das bezweifle ich.

    [...]

    Ahh, ich glaube ich weiß was du meinst: Das beide abgearbeitet werden, bevor die Gesamtausgabe erfolgt? Nein, so hatte ich das auch nicht gemeint. Besser formuliert:
    ...aber es ist garantiert, dass sie jeweils beide abgearbeitet werden, bevor die eigentliche Ausgabe geschieht, [...]

    Na gut, aber in der Lesart ist es ja eine völlig triviale Aussage. Ohne diese Garantie hätte die Ausgabe ja nichts zum ausgeben.


  • Mod

    Bashar schrieb:

    Na gut, aber in der Lesart ist es ja eine völlig triviale Aussage. Ohne diese Garantie hätte die Ausgabe ja nichts zum ausgeben.

    Für uns. Dem TE war das anscheinend nicht wirklich klar, wie genau solche Ausdrücke abgearbeitet werden.



  • SeppJ schrieb:

    Bashar schrieb:

    Na gut, aber in der Lesart ist es ja eine völlig triviale Aussage. Ohne diese Garantie hätte die Ausgabe ja nichts zum ausgeben.

    Für uns. Dem TE war das anscheinend nicht wirklich klar, wie genau solche Ausdrücke abgearbeitet werden.

    War mir in der Tat nicht klar, dass da für zwei verschiedene Objekte die Funktion gleiches zurücklieferte. Habs aber dank der guten Erklärung jetzt verstanden (denk ich mal :p )



  • Naja, wie hier schon erwähnt wurde, wenn Du eine Referenz zurückgeben willst/musst, dann vereinbare die Variable datum als Member Deiner Klasse - nicht static versteht sich - dann ist das kein Problem.



  • alles klar 😉


Anmelden zum Antworten