我有一个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/

10-10 12:44