0

I am new to using smart pointers and have only used unique_ptr so far. I am creating a game and I am using a vector of unique_ptr to store my game states.

Here is my vector code:

std::vector<std::unique_ptr<GameState>> gameStates;

Here is my question. Are the following functions going to work to control my vector:

void GameStateManager::popGameState(){
    if (getCurrentGameState() != nullptr)
        gameStates.pop_back();
}

void GameStateManager::pushGameState(GameState *gameState){
    gameStates.push_back(std::unique_ptr<GameState>(gameState));
}

GameState *GameStateManager::getCurrentGameState(){
    return gameStates.back().get();
}

My worries where that using raw pointers as arguments and to return the current game state would eliminate the point of using smart pointers. Is this a good way to do this?

Kara
  • 6,115
  • 16
  • 50
  • 57
Dennis Harrop
  • 167
  • 1
  • 7
  • 1
    Raw pointers are fine as long as they don't own memory, but do look into move semantics particularly for `pushGameState`. – user703016 Jun 18 '14 at 11:00
  • 1
    That `popGameState` is weird. What does the `if` mean there? If you do not want to pop from an empty `vector` check that with `if(!gameStates.empty())`. – Csq Jun 18 '14 at 11:06
  • If someone does `GameState g; gameStateManger.pushGameState(&g);` things will break. To prevent that `pushGameState` should require a `unique_ptr`. – nwp Jun 18 '14 at 11:20
  • 1
    Is `GameState` polymorphic? If not, from its name, it sounds more like you want a `std::vector`, with no pointers what so ever. – James Kanze Jun 18 '14 at 11:23

1 Answers1

1

Try this:

void GameStateManager::pushGameState(std::unique_ptr<GameState> gameState){
    gameStates.push_back(std::move(gameState));
}

std::unique_ptr cannot be copied, but it can be moved.

I think it has some benefits.. For example, Look at this code.

std::unique_ptr<GameState> pgs;
...
gsm.pushGameState(pgs); // error!
gsm.pushGameState(std::move(pgs)); // you should explicitly move it

If you use raw pointers ...,

void GameStateManager::pushGameState(GameState *gameState) { ... }

{
    std::unique_ptr<GameState> pgs;
    ...
    gsm.pushGameState(pgs.get()); // IT'S NOT COMPILE ERROR! you can make some mistakes like this..
    gsm.pushGameState(pgs.release()); // you can use it, but I think you will make a mistake sometime, finally.
} // if you use `pgs.get()`, the `GameState` is deleted here, though `gameStates` still contains it.
ikh
  • 10,119
  • 1
  • 31
  • 70
  • Thankyou for your suggestion could you please explain how this would work as I do not understand fully the use of the double reference. – Dennis Harrop Jun 18 '14 at 11:03
  • 2
    You may want to read [What is move semantics?](http://stackoverflow.com/questions/3106110/what-is-move-semantics) – user703016 Jun 18 '14 at 11:04
  • 1
    @DennisHarrop please see edit, which explain the benefit of use that. If you want to know about rvalue-reference, see William's link. (and please choose >o<) – ikh Jun 18 '14 at 11:10
  • 2
    I don't see a good reason for using an rvalue reference here. Why is it not just taken by value? – Joseph Mansfield Jun 18 '14 at 11:23