Smartpointer Problem



  • Für mich hört sich das Konzept merkwürdig an. Aber ohne Details zu kennen (die ich eigentlich auch gar nicht kennen will) kann man wenig dazu sagen.
    Möglicherweise wäre das Problem mit Templates zu lösen.



  • Hi,

    vielleicht hab ich den Sinn von GameStates auch nicht verstanden 😉

    Für mich ist zB das Start-Menu ein Gamestate.
    Wenn ich aber 2 verschiedene Spiele mit der gleichen Engine programmiere, sind die Menus doch völlig unterschiedlich zueinander.
    Deshalb kann der Manager die ja auch nicht kennen.

    Ich wollte dann im eigendlichen Spiel einfach eine Klasse von meinem Abstrakten Gamestate ableiten und an den Manager schicken.
    Wenn das Spiel dann beendet wird, sollen auch alle Gamestates gelöscht werden (deshalb dachte ich an unique_ptr im GameStateManager).

    Gruß



  • Also zu dem ganzen Gamestate-Ansatz sage ich mal nichts, mach da ruhig einfach mal weiter, wenn's dann am Ende nicht perfekt ist hast du ja zumindest was gelernt. Und hey, irgendwie wird es schon funktionieren. Wegen dem unique_ptr: std::move ist dein Freund!

    #include <vector>
    #include <memory>
    
    class game_state
    {};
    
    class game_state_manager // Damn a manager class :(
    {
    	std::vector<std::unique_ptr<game_state>> game_states_;
    
    public:
    	game_state* add_state(std::unique_ptr<game_state> state)
    	{
    		game_states_.push_back(std::move(state));
    		return game_states_.back().get();
    	}
    };
    
    int main()
    {
    	game_state_manager gsm;
    	auto state = std::make_unique<game_state>();
    	auto state_ptr = gsm.add_state(std::move(state));
    }
    

    So in etwas wolltest du das, oder? Alles verstaendlich? RValue-References und std::move solltest du dir vermutlich noch mal angucken. 😉



  • Hi,

    danke für den Code.

    Was gibts denn für Alternativen zu Gamestates? Ich will natürlich weiter dazulernen 😉

    Gruß



  • Gamestates ueber abstrakte Klassen verteilen sieht mir sehr nach overengeneering aus, denn ueblicherweise ist das eine einfache FSM.
    Meistens hat man ein enum fuer die ganzen Zustaende, die GameState-Klasse empfaengt events und ruft dann ueber ein switch die richtige Funktion auf. Das ist sehr viel konkreter und Funktionalitaet laesst sich leichter ergaenzen.



  • Hi,

    werden bei unique_ptr irgendwie bei der Initialisierung schon Objekte angelegt und wieder gelöscht?
    Ich habe das Problem, dass bei der Initialisierung Destruktoren von Objekten aufgerufen werden, die eigendlich noch garnicht existieren dürften.
    Diese Objekte sind nicht richtig initialisiert (vielleicht weil sie keinen Default-Konstruktor habe), deshalb gibts beim Löschen wieder Probleme.

    Gruß



  • Raven280438 schrieb:

    werden bei unique_ptr irgendwie bei der Initialisierung schon Objekte angelegt und wieder gelöscht?

    Hängt davon ab, ohne deinen Code zu sehen, kann man das nicht sagen...



  • Raven280438 schrieb:

    werden bei unique_ptr irgendwie bei der Initialisierung schon Objekte angelegt und wieder gelöscht?

    Nicht die Typen, auf die der Zeiger zeigt. Intern werden natürlich schon Objekte erzeugt.



  • manni66 schrieb:

    Intern werden natürlich schon Objekte erzeugt.

    Ist das so 'natürlich'? Was soll denn da erzeugt werden?



  • Jockelx schrieb:

    manni66 schrieb:

    Intern werden natürlich schon Objekte erzeugt.

    Ist das so 'natürlich'? Was soll denn da erzeugt werden?

    Der unique_ptr selber?



  • Jockelx schrieb:

    manni66 schrieb:

    Intern werden natürlich schon Objekte erzeugt.

    Ist das so 'natürlich'? Was soll denn da erzeugt werden?

    beispielsweise der Deleter... 😉



  • Mmh, ok, hab irgendwie aus dem 'no-size-overhead' geschlossen, dass da nichts erzeugt wird.
    Aber auch ein leerer Deleter muss ja erzeugt werden.



  • Hi,

    im Detail:

    Ich habe 2 Klassen:

    class Primitives::Triangle : public IRenderable
    {
    [...]
    ];
    
    class TestApp::TestState
    {
    private:
    std::unique_ptr<Primitives::Triangle> Triangle;
    [...]
    };
    

    Im Konstruktor der TestState-Klasse wird das Triangle erzeugt:

    this->Triangle = std::unique_ptr<Primitives::Triangle>(new Primitives::Triangle(glm::vec3(50, 100, 0), glm::vec3(100, 50, 0), glm::vec3(150, 100, 0)));
    

    Durch Breakpoints hab ich rausgefunden, es wird zuerst der Kontruktor der Triangle-Klasse aufgerufen, dann sofort wieder der Destruktor.
    Beim Beenden des Programms wird dann nochmal der Destruktor der Triangle-Klasse aufgerufen, was zu Problemen führt.

    Liegt das an dem unique_ptr, oder hab ich irgendwo anders im Programm einen Fehler?

    Gruß



  • Wieso muss das Triangle überhaupt mit new erzeugt werden, wieso nicht einfach

    class TestApp::TestState
    {
    private:
     Primitives::Triangle Triangle;
    [...]
    };
    

    Raven280438 schrieb:

    Durch Breakpoints hab ich rausgefunden, es wird zuerst der Kontruktor der Triangle-Klasse aufgerufen, dann sofort wieder der Destruktor.
    Beim Beenden des Programms wird dann nochmal der Destruktor der Triangle-Klasse aufgerufen, was zu Problemen führt.

    Das ist sehr merkwürdig, kann es sein, dass der TestState gleich wieder zerstört wird? Und wieso führt das du Problemen?


Anmelden zum Antworten