Problem mit Objekterstellung
-
Hallo,
Ich habe ein Verständnisproblem mit folgendem Code:
////// resourcemanager.h class Texture { public: int* counter; ~Texture(); }; class ResourceManager { private: map<string, int> textures; public: Texture getTexture(const char* texname); void print(); }; ////// resourcemanager.cpp Texture::~Texture() { cout<<"Destructor"<<endl; (*counter)--; } Texture ResourceManager::getTexture(const char *texname) { textures[texname]++; Texture t; t.counter = &textures[texname]; return t; } void ResourceManager::print() { map<string, int>::iterator it; for(it = textures.begin(); it != textures.end(); ++it) { cout<< it->first << " counter = " << it->second <<endl; } } ////// main.cpp struct Triangle { Texture tex; }; int main() { ResourceManager rm; /* Version 1 Texture t1 = rm.getTexture("bla"); */ /* Version 2 Triangle t; t.tex = rm.getTexture("bla"); */ Texture t2 = rm.getTexture("blubb"); rm.print(); return 0; }Wenn ich Version 1 ausführe bekomme ich die gewünschte folgende Ausgabe:
bla counter = 1
blubb counter = 1
Destructor
DestructorWenn ich aber Version 2 ausführe erhalte ich diese Ausgabe:
Destructor
bla counter = 0
blubb counter = 1
Destructor
DestructorWie es aussieht wurde hier irgendwie ein Objekt mehr erstellt und vor der Ausführung von "rm.print();" schon zerstoert. Kann mir jemand erklären warum das so ist und wie ich das gleiche Verhalten bei beiden Versionen hinbekomme? (Ich will einen Resource Manager programmieren wo ich Texturen anfordern kann und der sicherstellt, dass jede Textur genau einmal geladen wird und auch wieder zerstört wird sobald die Textur nicht mehr verwendet wird)
-
Hallo MaxJ
Bei version 2 wird die Textur von getTexture erstellt und dann in das Triangle-struct kopiert, dann wird die Textur beim verlassen von getTexture gelöscht(darum der Destruktor). Bei version 1 kann diese Kopie vom Kompiler wegoptimiert werden, da die Adresse noch nicht feststeht. Du kannst version 2 optimieren indem du in getTexture die Textur erstellst und dann nur die Adressen der Texturen zurückgibst.
Gruss Ganesh123
-
Hmm, ok also hat der Compiler da irgendwas gemacht. Danke schon mal.
Aber wie funktioniert das Optimieren genau was du ansprichst? Ich würde jetzt die Funktion getTexture so ändern:
Texture* ResourceManager::getTexture(const char *texname) { textures[texname]++; Texture* t = new Texture(); t->counter = &textures[texname]; return t; }So ähnlich habe ich es eigentlich früher auch schon gemacht, aber da habe ich ja den Nachteil dass ich im Programm auch Zeiger verwenden und am Ende immer delete aufrufen muss. (diese Lösung wäre aber für mich akzeptabel wenn es nicht auch noch anders geht)
-
So habe ich mir getTexture vorgestellt.
Du könntest Smartpointer verwenden. Die löschen das Objekt auf das sie zeigen von alleine, wenn du es nicht mehr brauchst.Gruss Ganesh123
-
Ok, danke! Ich werde mir mal Smartpointer anschauen.