Verwirrende Ausgabe
-
Anonymus42 schrieb:
Habe jetzt nachgeschaut, die Lösung des Autors sieht genauso aus wie meine, ich denke mal es ist ja auch ok, wenn die static-Variable dann einfach immer überschrieben wird. Bei den Lösungen ruft er die Funktion aber nicht in einem if-else-zweig auf, deshalb hab ich hier gefragt, warum das da nicht funktioniert

Wo kommt diese Aufgabe her? Das ist nämlich absoluter Schwachsinn. Vernünftig wäre in dieser Situation die Rückgabe des strings als Kopie, wier hier schon erwähnt wurde. Referenz ginge noch, wenn die Variable als Member gehalten wird. Aber das mit static zu lösen - da zweifle ich doch ernsthaft an der Kompetenz des Lösungsschreibers.
-
Anonymus42 schrieb:
Habe jetzt nachgeschaut, die Lösung des Autors sieht genauso aus wie meine, ich denke mal es ist ja auch ok, wenn die static-Variable dann einfach immer überschrieben wird. Bei den Lösungen ruft er die Funktion aber nicht in einem if-else-zweig auf, deshalb hab ich hier gefragt, warum das da nicht funktioniert

Nein, es ist überhaupt nicht ok und birgt grosse Probleme im Bereich Multithreading. Auch sonst ist es unschön, da es eine (unsichtbare) Abhänigkeit zwischen den Instanzen der Klasse schafft.
-
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
asStringaufgerufen 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
mutableeinzuführen. Das mitstaticzu 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.
-
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.
-
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
