【问题标题】:How to turn vector of raw pointers into a vector of unique pointers?如何将原始指针向量转换为唯一指针向量?
【发布时间】:2015-02-01 12:44:13
【问题描述】:
#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”不起作用。现在好了
  • 一般来说,在您的问题中包含“不起作用”的内容可能是个好主意。
  • 看起来你的 GameState 类需要一个 virtual 析构函数。
  • @Galik 为什么?游戏状态没有指针,所有大对象都是全局的。其他的则是自我毁灭的智能课程。
  • GameState 有一个纯虚函数,这意味着您将只使用子类,并且这些子类将从基指针中删除(通过智能指针)。没有虚拟 dtor,这是未定义的行为。

标签: c++ smart-pointers raii raw-pointer


【解决方案1】:

只需将矢量更改为:

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 后立即将原始指针放入unique_ptr(或者最好使用std::make_unique)。否则,如果在unique_ptr 中分配和包装之间引发异常,则您有内存泄漏。

它与unique_ptr 无关,但与您的GameStateshould have a virtual destructor 无关。

Live demo

【讨论】:

  • 试试看。在继续之前,还要阅读您的 C++11 书籍。
  • 我想我需要另一本书。
  • 实际上,Chris,您的回答现在有点误导:push_back 将在 unique_ptr 上正常工作,即使没有 std::move - 只要被推送的对象是临时的。 emplace_back 不是必需的,因为 unique_ptr 是不可复制的,这是必需的,因为没有从原始指针到 std::unique_ptr 的隐式转换。
  • @Chris 现在很完美。
  • @JonathanWakely 我想我会完全摆脱emplace_back 的建议我想不出在这种情况下使用它的充分理由。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-03
  • 1970-01-01
  • 1970-01-01
  • 2011-08-04
  • 2015-05-29
  • 2014-04-02
  • 1970-01-01
相关资源
最近更新 更多