4

Possible Duplicate:
C++: Delete this?

I am trying to create a system to manage states for a game.

The issue with my current design is that when I switch states, the old state is deleted before control switches over to the new state.

The following is a simplified version of my code:

class StateManager;

class State
{
public:
    virtual void update(StateManager &manager)= 0;
    virtual ~State(){}
};


class StateManager
{
public:
    void setState(std::unique_ptr<State> && newState )
    {
        currentState = std::move(newState);
    }
    std::unique_ptr<State> currentState;

    void run()
    {
        currentState->update(*this);
    }
};

Notice how if a State object calls StateManager::setState while in the update method, there will be a period of time when a member function is being called on an object that has just been destroyed.

A complete example of this behavior is at http://ideone.com/WHLzJL. Note how the destructor for FirstState is called before FirstState::update returns.

Is this undefined behavior in C++? If so, how should I change my design?

Community
  • 1
  • 1
  • 1
    Perhaps not quite an *exact* duplicate, but the answers to [another question](http://stackoverflow.com/q/3150942/179910) cover this as well. – Jerry Coffin Nov 02 '12 at 23:12
  • @JerryCoffin I believe 'exact duplicate' should be extended as 'exact duplicate or strict subset'... –  Nov 02 '12 at 23:18

3 Answers3

7

No, it's okay, if you are careful: https://isocpp.org/wiki/faq/freestore-mgmt#delete-this

Vlad
  • 35,022
  • 6
  • 77
  • 199
2

There's no problem as long and it is the last thing you do in the function. (delete this is a common idiom.) In this particular case, however, I've generally found it preferable for State::update to return the new State (which could be this). The code which calls it in StateManager will then simply assign it to the pointer.

Be careful of the semantics of smart pointers in this case. I did it using an invasive shared pointer, but I suspect that most of the current smart pointers will fail here. On the other hand, you don't really need a smart pointer here, so why add the complication.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
0

As far as I know, the main effect is that this becomes a dangling pointer, so accessing fields, calling virtual methods or doing something like dynamic_cast<T*>(this) that relies on run-time type information would result in undefined behavior.

Jeffrey Hantin
  • 35,734
  • 7
  • 75
  • 94