My game's main loop looks like this:
std::vector<std::unique_ptr<State>> states;
for(size_t i = 0; i < states.size(); i++)
{
states[i]->Update();
states[i]->Draw();
}
Their is a flaw with this though. I can't modify the vector (delete a state) during the iteration because if I deleted the current state the iteration is on then it breaks obviously because there is no state to call update and draw on. So I thought it would be a good idea to make a vector of states that should be added to the states
vector and make a vector of states that should be deleted to the states
vector. Then after the loop is over modify the states
vector and no problems will occur mid iteration.
std::vector<std::unique_ptr<State>> states;
std::vector<std::unique_ptr<State>> statesToBeAdded;
std::vector<std::unique_ptr<State>> statesToBeRemoved;
for(size_t i = 0; i < states.size(); i++)
{
states[i]->Update();
states[i]->Draw();
}
for(size_t i = 0; i < statesToBeAdded.size(); i++)
{
states.push_back(std::move(statesToBeAdded[i]));
}
statesToBeAdded.clear();
for(size_t i = 0; i < statesToBeRemoved.size(); i++)
{
states.erase(std::remove(states.begin(), states.end(), statesToBeRemoved[i]), states.end());
}
statesToBeRemoved.clear(); //error is thrown here
I can't delete states from the states
vector though, an error is thrown on the statesToBeRemoved.clear()
line and I think it's because when I call the states.erase(...)
line it deletes the element from the states
vector which consequently nullifies the same element in the statesToBeRemoved
vector since that element points to an object that no longer exists.
You can't just delete a std::unique_ptr without destroying what the pointer points to so I don't think there is a way to delete the element from the states
vector without nullifying the element in the statesToBeRemoved
vector. So how do solve this problem?
Thanks.
Different pointer types cater for different ownership semantics:
unique_ptr
s are for unique ownership, this is why your current code does not workshared_ptr
s are for shared ownership - when the last shared_ptr
managing an object goes out of scope, it is destroyed*
) don't really say anything about the semantics they are modeling, but you have to enforce all constraints manually - that's what makes them dangerous. They are however, safe, (and in my opinion the sensible choice) for pointers that do never have ownership of the object pointed to.So: Your statesToBeAdded
is safe as long as you can guarantee that you never have anything in there that isn't already in states
. statesToBeRemoved
is different: The objects are already there and in states
, and it would make sense to have states
take ownership of the objects - hence raw pointers would be a fair choice for statesToBeRemoved
.
Note that all this is based on the few lines of code you have shown, depending on the circumstances it may well be that it makes sense to store State
s instead of unique_ptr<State>
s in your states
, etc ...