Unterschiedliche Ausgabe mit und ohne Zuweisung
-
Hallo,
folgendes Programm:
#include <iostream> using namespace std; class Dummy { public: int state; Dummy(int i) { state = i; } }; Dummy & funk(Dummy x) { x.state = -x.state; return x; } int main() { Dummy d1(2); Dummy & dr1 = funk(d1); cout << funk(d1).state << endl; // -2 cout << dr1.state << endl; // ??? return 0; }Wieso ist hier die Ausgabe unterschiedlich? Ich verstehe das nicht. Kann mir das einer erklären?
Vielen Dank!
-
Du gibst eine Referenz auf ein Objekt zurück, das es nicht mehr gibt. Entweder nimmt funk den Parameter x per Referenz oder du gibst eine Kopie zurück. So wie es jetzt ist, kann das nicht funktionieren.
-
UBerklärer schrieb:
Du gibst eine Referenz auf ein Objekt zurück, das es nicht mehr gibt. Entweder nimmt funk den Parameter x per Referenz oder du gibst eine Kopie zurück. So wie es jetzt ist, kann das nicht funktionieren.
funk(d1);1. Es wird eine Kopie erstellt.
2. Anschließend wird der Wert x von dieser Kopie negiert.
3. Die Referenz wird zurückgegeben- Heißt das, dass das Original zurückgegeben wird?
Welches Objekt gibt es nicht mehr und wieso?
-
Heißt das, dass das Original zurückgegeben wird?
Nein, sondern eine Referenz auf die funktionslokale Kopie.
Welches Objekt gibt es nicht mehr
Der Funktionsparameter.
und wieso?
Weil er beim Verlassen der Funktion zerstört wurde.
-
Ich verstehe es nicht.
funk(d1).state1. Es wird eine Kopie erstellt.
2. Anschließend wird der Wert x von dieser Kopie negiert.
3. Die Referenz von Kopie wird zurückgegeben.
4. state wird ausgegeben.Dummy & dr1 = funk(d1);1. Es wird eine Kopie erstellt.
2. Anschließend wird der Wert x von dieser Kopie negiert.
3. Die Referenz von Kopie wird zurückgegeben.
4. Zuweisung von Referenz auf &dr1
5. dr1.state wird ausgegeben.Wo ist genau das Problem? Welcher Schritt ist was?
-
Welcher Schritt ist falsch, sollte es heißen.
-
Es fehlen ein paar Schritte:
funk(d1).state1. Es wird eine Kopie erstellt.
2. Anschließend wird der Wert x von dieser Kopie negiert.
3. Die Referenz von Kopie wird zurückgegeben.
4. Die Kopie wird gelöscht, weil die Funktion fertig ist
5. state wird ausgegeben von einem Objekt, das nicht mehr existiert.Dummy & dr1 = funk(d1);1. Es wird eine Kopie erstellt.
2. Anschließend wird der Wert x von dieser Kopie negiert.
3. Die Referenz von Kopie wird zurückgegeben.
4. Die Kopie wird gelöscht, weil die Funktion fertig ist
5. Zuweisung von Referenz auf &dr1 auf etwas, das nicht mehr existiert
5. dr1.state wird ausgegeben**, existiert aber nicht mehr**.Wenn du auf etwas zugreifst, was nicht mehr existiert, passieren komische Dinge. Der offizielle Begriff dafür ist "Undefiniertes Verhalten".
-
Ja aber für
funk(d1).stateStimmt die Ausgabe immer. Wenn die Kopie gelöscht wird, dann sollte doch die Ausgabe auch nicht mehr stimmen?
-
Undefiniertes Verhalten ist nunmal undefiniert - natuerlich kann ein erwartetes Ergebnis eintreten.
Auf meiner Maschine bekomme ich nur Muellwerte. Liegt vielleicht an einer Optimierung; dass der Stack direkt ueberschrieben wird ist ja AFAICS nicht moeglich... ?
-
Ich bekomme jedes mal -2. Benutze Visual Studio 2013.
-
klempner schrieb:
Ich bekomme jedes mal -2. Benutze Visual Studio 2013.
Das erzeugte Programm ist in der Regel* schon noch deterministisch. Bloß ist nicht vorher zu sehen, was für eine Art Verhalten ein anderes Programm erzeugen würde, das aus dem gleichen Code mit einem anderen Compiler erzeugt wird. Oder mit dem gleichen Compiler, mit leicht anderen Einstellungen. Spiel beispielsweise mal an Optimierungseinstellungen rum.
*: Aber nicht garantiert immer! Bei komplizierteren Programmen (z.B. mit paralleler Abarbeitung) kann ein undefiniertes Programmverhalten auch gerne mal bei jedem Aufruf anders sein.
-
Okay, Danke
