Search code examples
c++smart-pointersraiiraw-pointer

How to turn vector of raw pointers into a vector of unique pointers?


#include <vector>

enum ListOfGameStates
{
    // List of game states
};

class GameState()
{
    public:
        GameStates(); // Initializes protected (global) variables
        virtual ListOfGameStates run() = 0;
    protected:
        // Heavyweigh resource managers containing all resources and other global vars
}

class GameStateManager()
{
    public:
        GameStateManager();  // Creates all game states
        ~GameStateManager(); // Deletes all game states
        void run();          // Switches from one state to another state
    private:
        // A vector of raw pointers to game states. GameState is a base class.
        std::vector<GameState*> game_states_container;
}

I want to get rid off raw pointers so that I could have no worries about exceptions and clean-up. Is there an easy simple solution (I am a really dumb teen) or is it not worth it? Thanks!


Solution

  • Simply change your vector to:

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

    And get rid of any delete in your destructor. In fact you can probably get rid of the destructor entirely unless it has other jobs to do.

    unique_ptr is not copyable but it is movable so it is worth having some understanding of C++11 move-semantics. When you want to add a unique_ptr to your container you can use push_back providing you pass a temporary, e.g the return value of a function:

    game_states_container.push_back(createGameState());
    game_states_container.push_back(std::make_unique<GameStateA>());  // C++14
    

    Or if you have a local unique_ptr variable you can use std::move to move it into the vector:

    std::unique_ptr<GameState> game_state = std::make_unique<GameStateA>();  // C++14
    // auto game_state = std::unique_ptr<GameState>(new GameStateA);  // C++11
    ...
    game_states_container.push_back(std::move(game_state));
    

    It is good practice to put the raw pointers in unique_ptr as soon as you new them (or preferably use std::make_unique). Otherwise, if an exception is thrown between allocation and wrapping in unique_ptr you have a memory leak.

    It is unrelated to unique_ptr but your GameState class should have a virtual destructor.

    Live demo