我有一个Singleton ButtonManager
,其中包含一个Button
对象的向量。 ButtonManager
主题之所以存在,是因为它在调用Button
时将事件分发给所有HandleEvents
观察者。由于某些其他原因,它必须是Singleton。
我的问题是我想不再需要Button
手动将自己从ButtonManager
中删除。理想情况下,在我Create
一个Button
范围的末尾,ButtonManager也将丢失对其的引用。
class ButtonManager : public EventHandler
{
public:
static ButtonManager & Instance();
public:
// push_back a Button to the vector and return it
std::shared_ptr<Button> Create(const Rect & _rect, const std::string _text, const Colour & _fg, const Colour & _bg);
// Erase the button pointer from the vector
void Remove(const std::shared_ptr<Button> & _button);
// EventHandler
void HandleEvents( const Event & _event );
...
private:
std::vector<std::shared_ptr<Button>> buttons;
};
class Button : public EventHandler
{
public:
Button(const Rect & _rect, const std::string & _text, const Colour & _fg, const Colour & _bg);
...
// EventHandler
void HandleEvents( const Event & _event );
};
当前场景:
{
std::shared_ptr<Button> ok_button_ptr = UI::ButtonManager::Instance().Create(UI::Rect(5, 5, 5, 1), string("OK"), UI::Colour::White, UI::Colour::DodgerBlue);
// events are processed and distributed to the buttonmanager
// which then distributes to the buttons
UI::ButtonManager::Instance().Remove(ok_button_ptr);
}
理想方案:
{
std::shared_ptr<Button> ok_button_ptr = UI::ButtonManager::Instance().Create(UI::Rect(5, 5, 5, 1), string("OK"), UI::Colour::White, UI::Colour::DodgerBlue);
// events are processed and distributed to the buttonmanager
// which then distributes to the buttons
// ok_button_ptr loses its reference here and the ButtonManager erase's the shared_ptr as well if it holds the last reference to the Button
}
最佳答案
可以在RAII处完成作用域退出时释放资源。创建一个ButtonHolder类,该类将shared_ptr保留为成员,并在其析构函数中调用Remove
class ButtonHolder
{
public:
ButtonHolder(std::shared_ptr<Button> b): theButton(std::move(b)) {}
~ButtonHolder() {
UI::ButtonManager::Instance().Remove(theButton);
}
// could give it shared_ptr interface, e.g.
Button& operator*() const;
Button& operator->() const;
// etc
private:
std::shared_ptr<Button> theButton;
};
{
// get button from singleton. Ref count increases by one. Let's say it is now 2.
ButtonHolder ok_button_ptr( UI::ButtonManager::Instance().Create(...) );
// events are processed and distributed to the buttonmanager
// which then distributes to the buttons
// ButtonHolder::~ButtonHolder is called which removes the button from the
// singleton (ref count = 1) and then deletes its own shared_ptr member (ref count = 0)
// to delete the button object completely
}
关于c++ - 如何在创建范围结束时自动从Singleton Manager类中删除shared_ptr,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22816115/