我正在构建一个控制台应用程序,我只使用智能指针。我选择只使用智能指针来学习何时使用哪个智能指针。在这个应用程序中,我试图使用状态模式在不同的状态之间切换。基类是此类中的TurnState,所有其他状态类都继承。
在游戏控制器中,我已经定义了当前的状态。为了在状态之间切换,我想使用带有枚举作为键的unordered_map和作为值的状态类。但是当我在标题内写下std::unordered_map<TurnStateEnum, std::shared_ptr<TurnState>> _turn_states_map;
时,我发现了一些内存泄漏。
为了摆脱那些内存泄漏,我试图在解构器中销毁它们,如下所示:
GameController::~GameController()
{
for (std::unordered_map<TurnStateEnum, std::shared_ptr<TurnState>>::iterator iterator{ _turn_states_map.begin() }; iterator != _turn_states_map.end(); iterator++) {
iterator->second.reset();
_turn_states_map.erase(iterator);
}
_turn_states_map.clear();
}
但这也没有用。我能够使用原始指针解决它,但这不是我想要实现的。所以我的问题是,如何以正确的方式删除带有shared_ptrs的地图?
所有帮助将不胜感激。
游戏控制器将用于将shared_ptr保持到当前状态并切换到下一个状态。
下面是GameController标题:
class GameController
{
public:
GameController();
~GameController();
void do_action(Socket& client, Player& player, std::string command);
void set_next_state(TurnStateEnum state);
private:
std::unordered_map<TurnStateEnum, std::shared_ptr<TurnState>> _turn_states_map;
std::shared_ptr<TurnState> _turn_state;
void initialize_turn_states_map();
};
以下是GameController来源:
GameController::GameController()
{
initialize_turn_states_map();
_turn_state = _turn_states_map.at(TurnStateEnum::SETUP);
}
GameController::~GameController()
{
for (std::unordered_map<TurnStateEnum, std::shared_ptr<TurnState>>::iterator iterator{ _turn_states_map.begin() }; iterator != _turn_states_map.end(); iterator++) {
iterator->second.reset();
_turn_states_map.erase(iterator);
}
_turn_states_map.clear();
}
void GameController::do_action(Socket& client, Player& player, std::string command)
{
_turn_state->do_turn(client, player, command);
}
void GameController::set_next_state(TurnStateEnum state)
{
_turn_state = _turn_states_map.at(state);
}
void GameController::initialize_turn_states_map()
{
_turn_states_map.insert(std::make_pair(TurnStateEnum::SETUP, std::make_shared<SetupState>(*this)));
}
TurnState是基类。此类应包含应用程序的当前逻辑/行为。 在TurnState标题下面:
class GameController;
class TurnState
{
public:
TurnState(GameController& gameCtrl);
virtual ~TurnState();
void next_state(TurnStateEnum stateEnum);
virtual void do_turn(Socket& client, Player& player, std::string command) = 0;
protected:
GameController& _gameCtrl;
};
在TurnState来源下面:
TurnState::TurnState(GameController& gameCtrl) : _gameCtrl ( gameCtrl )
{
}
TurnState::~TurnState()
{
}
void TurnState::next_state(TurnStateEnum stateEnum)
{
_gameCtrl.set_next_state(stateEnum);
}
Setup State除了他的基类之外没有任何其他变量或方法,而且现在这些方法都是空的。
这可能是一个更好的最小例子。我创建了一个控制台项目并将其上传到:https://ufile.io/ce79d
答案 0 :(得分:0)
您的计划中没有泄密。您正确使用std::shared_ptr
。没有循环引用来修复。虽然破坏者是多余的,但它们是无害的。
您只是没有使用_CrtDumpMemoryLeaks()
权利。在运行main
中的本地对象的析构函数之前调用它。当然,它会将这些对象分配的内存报告为泄漏。
修复:
int main(int argc, const char * argv[])
{
(
GameController gameCtrl = GameController();
gameCtrl.do_action("test");
}
_CrtDumpMemoryLeaks();
return 0;
}