Objekt plötzlich deinitialisiert
-
Hey!
Ich komme nicht weiter. Ein Objekt, welches existiert, bis das Programm beendet wird, ist im Konstruktor meiner Klasse noch initialisert, und dann plötzlich in einer Funktion der Klasse nicht mehr. Dabei gehört das Objekt selbst zu einer Klasse. In etwa so:
class Renderer { LPDIRECT3DDEVICE9& direct3DDevice; LPDIRECT3DDEVICE9 direct3DDeviceDummy; Map& currentMap; public: Renderer(); ~Renderer(); void Init(LPDIRECT3DDEVICE9&); void Tick() { if(currentMap.vertices == 24) MessageBox(0, "6", "", MB_OK); } void changeMap(Map&); };void Renderer::changeMap(Map& map) { currentMap = map; if(currentMap.vertices == 24) MessageBox(0, "5", "", MB_OK); }Also, die MessageBox mit "5" wird angezeigt. Die mit "6" allerdings nicht. Das Objekt map existiert jedoch. Warum ist es in Tick() dann plötzlich deinitialisiert? Die Reihenfolge stimmt schon, zuerst wird changeMap, dann Tick aufgerufen. In Tick() ist auch der IndexBuffer nicht mehr gültig, vertices hat den Wert 56800 oder so...
Es passiert sonst nur das:
renderer.changeMap(resourceManager.getMap());
Map& ResourceManager::getMap() { return map; }Ich verstehe es einfach nicht. Wie kann das sein?
-
Zeig mal den Source, wo du Tick aufrufst...
-
ceplusplus schrieb:
...Dabei gehört das Objekt selbst zu einer Klasse. ...
Also, falls es sich dabei um
currentMaphandelt, so gehört das Objekt NICHT zur Klasse. Sie hält lediglich eine Referenz darauf. Es kann also relativ problemlos noch zu Lebzeiten des Rendereres (von außen) "abgeräumt" werden.Wie weist Du currentMap eigentlich erstmalig zu ?
Eigentlich muß das im Konstruktor (Initialisierungsliste) geschehen, sonst gibt's Compiler-Haue....Ich sage mal so: Der Code von oben compiliert definitiv nicht - ich vermute, Dein Problem liegt in dem "Weggelassenen Teil" des Codes...
Vielleicht wolltest Du auch das schreiben:
class Renderer { ... Map currentMap; // ohne '&' ...Damit müsste Dein Code prinzipiell funktionieren (wenn Du beim changeMap() eine fachlich sinnvolle Map übergibst)....
Ach ja: Und da Dein getMap() vermutlich eine (non-const)-Referenz auf die currentMap (einen Tippfehler von Dir mal vorausgesetzt) rausgibt, kann Dir jeder, der die Funktion aufrufen kann, Deine currentMap zerschießen....
Gruß,
Simon2.
-
Jo sorry ich werde für Klarheit sorgen! An currentMap wird nicht herumgepfuscht. Die Referenz wird einmalig initialisiert...
Renderer::Renderer() : direct3DDevice(direct3DDeviceDummy), currentMap(Map(0, 0)) { ; }Und nach
renderer.changeMap(resourceManager.getMap());
ist currentMap gleich das map-Objekt der Klasse ResourceManager, welches durchgehend existiert.
In Renderer::changeMap() stimmt ja noch alles, aber danach in Renderer::Tick() stimmt alles nicht mehr...
Mit map passiert sonst garantiert nichts mehr. renderer.Tick() wird erst aufgerufen, nachdem Renderer und ResourceManager aufgebaut wurden.
MfG
-
In deinem Konstruktor bindest du deinen Referenz (currentMap) an ein temporäres Objekt. Das geht so nicht.
In deinem Fall würde ich eher einen Pointer auf die Map speichern und den anfangs mit 0 initialisieren.
-
ceplusplus schrieb:
...Die Referenz wird einmalig initialisiert...
...
Und nachrenderer.changeMap(resourceManager.getMap());
ist currentMap gleich das map-Objekt der Klasse ResourceManager, welches durchgehend existiert....
"gleich" (im Sinne von identischen Werten) vielleicht, aber trotzdem nicht "gleich" (im Sinne von "auf dasselbe Objekt verweisend").

Referenzen kann man nur einmal "binden" ...void Renderer::changeMap(Map& map) { currentMap = map; ... };Damit übernimmt currentMap nicht die Adresse des übergebenen Map-Objektes, sondern nur die "Werte seiner Attribute" (oder was immer der Map::operator=() so treibt).
Entweder musst Du currentMap bereits im Renderer-Ctor an das ResourceManager::Map-Objekt binden:
Renderer::Renderer(Map& map) : currentMap(map) {} ... }; // im der nutzenden Funktion dann: RessourceManager rm; Renderer rend(rm.getMap());... oder eben (wie gesagt) mit Pointern arbeiten.
Oder als Antwort auf Deine ursprüngliche Frage: Du lässt selbst das Objekt abräumen (nach Ende des Renderer-CTors), auf das Du currentMap zeigen lässt und dessen Ableben Du beklagst.

Gruß,
Simon2.
-
Hey!
Also war mein Fehler, dass man eine Referenz nicht mehrfach auf ein Objekt "binden" kann? Das gibts doch nicht, so kenn ich das gar nicht mehr...
int a = 10; int b = 20; int& c = a; c = b;Funktioniert doch, versteh ich nicht...
MfG
-
Klar geht das. Du aber machst:
int& c = int();Und das geht nicht, weil das temporäre int, welches an die Referenz gebunden wird, nach diesem Ausdruck wieder verschwindet.
-
Ah, check
Danke. Aber komisch, wird dadurch die Referenz einfach ungültig? Denn wenn sie so auf ein Objekt zeigt, welches dann zerstört wird, kann man der Referenz doch auch ein neues Objekt zuweisen, oder?MfG
-
Nein, einer Referenz kannst Du nie etwas neues zuweisen. Deshalb funktioniert Dein changeMap auch nicht wie Du es vermutlich erwartest - dort wird der Inhalt des übergebenen Objekts in das Objekt kopiert, auf das die Referenz zeigt, es wird aber nicht die Referenz auf das neue Objekt verbogen.
-
Ok danke!
MfG
-
ceplusplus schrieb:
...
int a = 10; int b = 20; int& c = a; c = b;Funktioniert doch...
Nein !!!
Laß Dir mal nach der Zuweisung a ausgeben (oder die Adresse von a, b und c), dann wirst Du es sehen: c verweist immer noch auf a ... das hat aber nun den Wert 20 !
int a = 10; int b = 20; int& c = a; cout << a << " " << b << " " << c << "\n"; cout << &a << " " << &b << " " << &c << "\n"; c = b; cout << a << " " << b << " " << c << "\n"; cout << &a << " " << &b << " " << &c << "\n";Du musst zwischen der "Wertzuweisung" (ein Objekt wird mit den Werten eines anderen Objektes "konfrontiert" ;)) und der "Adresszuweisung" (eine Referenz/Zeiger zeigt auf ein Objekt) unterscheiden. Letzteres kannst Du bei C++-Referenzen nur einmal (und nur direkt bei der Initialisierung) machen....
Jede weitere Zuweisung auf eine Referenz wird als Wertzuweisung für das referenzierte Objekt behandelt.Gruß,
Simon.
-
LordJaxom schrieb:
Klar geht das. Du aber machst:
int& c = int();Und das geht nicht, weil das temporäre int, welches an die Referenz gebunden wird, nach diesem Ausdruck wieder verschwindet.
Neeee - geht trotzdem nicht (so wie ceplusplus das meint)

Aber nichtsdestotrotz hat er natürlich den "Temp-Fehler" zusätzlich gemacht.Gruß,
Simon2.