如何将原始指针的向量转换为唯一指针的向量?

3
#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;
}

我希望能够避免使用裸指针,这样我就不用担心异常和清理问题了。是否有一个 简单易懂的解决方案 (我是个真正的愚蠢的青少年),或者说这样做是否值得?谢谢!

抱歉,我之前有些困惑,因为 'push_back' 无法正常工作。现在已经解决了。 - user2933244
1
通常,在你的问题中包含哪些“不起作用”的信息可能是一个好主意。 - Chris Drew
1
看起来你的 GameState 类需要一个 virtual 析构函数。 - Galik
@Galik 为什么?游戏状态没有指针,所有大对象都是全局的。其他的是自毁智能类。 - user2933244
2
GameState拥有一个纯虚函数,这意味着您将只使用子类,并且这些子类将由基类指针通过智能指针进行删除。如果没有虚析构函数的话,这将是未定义的行为。 - Galik
好书推荐:https://dev59.com/_3RC5IYBdhLWcg3wK9yV - Galik
1个回答

7
只需要简单地将您的向量更改为:
std::vector<std::unique_ptr<GameState>> game_states_container;

请在析构函数中删除任何delete。事实上,除非析构函数还有其他任务要执行,否则您可能可以完全取消析构函数。

unique_ptr不可复制,但是可移动,因此值得了解C ++ 11的移动语义。当您想将unique_ptr添加到容器中时,可以使用push_back,只需传递一个临时对象,例如函数的返回值:

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

如果您有一个本地的unique_ptr变量,可以使用std::move将其移动到向量中:

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));

最好的实践是在你使用new(或者更好地使用std::make_unique)时就将原始指针放入unique_ptr中。否则,如果在分配内存和用unique_ptr封装之间抛出异常,你将会有一个内存泄漏。

这与unique_ptr无关,但是你的GameState应该有一个虚析构函数

在线演示


试一下,看看效果。在继续之前,也要把你的C++11书读到最后。 - Lightness Races in Orbit
我想我需要另一本书。 - user2933244
4
实际上,克里斯,你的回答现在有点误导人了:push_backunique_ptr 上可以很好地工作,即使没有 std::move,只要被推入的对象是一个临时对象。emplace_back 不是必需的,因为 unique_ptr 是不可复制的,它是必须的是因为从原始指针到 std::unique_ptr 没有隐式转换。 - Konrad Rudolph
1
@Chris 现在完美了。 - Konrad Rudolph
1
@JonathanWakely 我想我会完全放弃emplace_back的建议,因为我无法想出在这种情况下使用它的好理由。 - Chris Drew
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接