MVC std :: shared_ptr中的循环依赖

时间:2013-06-25 03:56:32

标签: c++ model-view-controller shared-ptr weak-ptr

我正在尝试为我的项目创建这个MVC结构。我第一次使用shared_ptr和weak_ptr,并且除了循环依赖之外还有很多问题。

模型是可观察的。 View is Observer。

class Observable
{
    std::set< std::shared_ptr<Observer> > observers;
public:
    Observable( void );
    void registerObserver( std::shared_ptr<Observer>  );
    void removeObserver( std::shared_ptr<Observer> & );
    void notifyObservers( void );
    virtual ~Observable( void );
};


class Observer
{
public:
    Observer(void);
    virtual void update() = 0;
    virtual ~Observer(void);
};

    class Model : public Observable 
{
public:
    Model(void);
    void internalStateChange();
    void funcForController();
    int getSomethingForView() const;
    ~Model(void);
};

class View :
public Observer
{
std::weak_ptr<Model> model;
std::shared_ptr<Controller> controller;
public:
View( const std::shared_ptr<Model> &, const std::shared_ptr<Controller> & );
void update() override;
~View(void);
};

class Controller
{
std::shared_ptr<Model> model;
std::shared_ptr<View> view;
public:
Controller( std::shared_ptr<Model> & );
void changeHappened() const;
~Controller(void);
};

我的输出是: enter image description here

这表明它挂在某处,然后在50秒之后终止,没有其他输出。 enter image description here

控制器没有被破坏。 :(

我如何解决问题?

1 个答案:

答案 0 :(得分:0)

此问题也在boost文档中有详细记载,请查看。 我自己写了一篇关于使用弱指针打破参考周期的快速注释作为我的硕士论文的附录(找到它here)。 请检查参考文献,因为主题不能完全涵盖两行。

标准库为程序员提供了两个不同的类(事实上,还有其他智能指针),即shared_ptrweak_ptr。共享指针是一个智能指针,用于保存指向对象的指针和指向共享引用计数器的附加指针。每次 使智能指针的副本自动引用计数 增加1.当共享指针被销毁(或用于引用不同的对象)时,其对象的引用计数器(或者对象的引用计数器) 它的上一个对象)递减了。从原始构造的共享指针 指针最初的引用计数为1.当引用计数器时 到达0时,指向的对象被自动销毁。弱点是 用于将循环分解为引用结构。他们可以 用于获取指向同一对象的共享指针并检查是否存在 对象已被破坏。它们不涉及引用计数。 弱指针不是要直接解除引用(即它们不能 用于访问引用的对象,这样做可能会导致 崩溃或随机行为;事实上,他们可以晃来晃去。)

至于你的具体问题,重点在于:你有一个班级

class Controller
{
public:
std::shared_ptr<View> view;
};

和另一个班级:

class View :
public Observer
{
public:
std::shared_ptr<Controller> controller;
};

并且你“分配”一个,即

std::shared_ptr<Controller> c(new Controller);
std::shared_ptr<View> v(new View);
c->view = v;
v->controller = c;

cv超出范围时,不会调用析构函数,因为cv->controller)仍有一个引用,{v有一个引用1}}(c->view)。

用两个词来说,解决方案是用shared_ptr替换两个weak_ptr中的一个。当然,你不是随便偷看其中一个,哪一个取代你的设计,你可能最终取代它们(这一切都取决于所有权的semanthics)。但是,如果您替换(至少)其中一个,问题就解决了。

对您在设计中所有参考周期的相同应用