3

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

模型是可观察的。视图是观察者。

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);
};

我的输出是: 在此处输入图像描述

这表明它在某处挂断,然后在 50 秒后终止,没有其他输出。 在此处输入图像描述

控制器没有被破坏。:(

我该如何解决这个问题?

4

1 回答 1

0

这个问题在 boost 文档中也有很好的记录,所以看看。我自己在我的硕士论文中作为附录写了一篇关于使用弱指针打破引用循环的快速注释(在这里找到它)。请检查参考资料,因为该主题不能用两行完全涵盖。

标准库为程序员提供了两个不同的类(事实上,还有其他智能指针)shared_ptr ,即weak_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超出范围时,不会调用析构函数,因为仍然有一个引用c( v->controller) 和一个引用v( c->view)。

用两个词来说,解决方案是将两个shared_ptrs 中的一个替换为 a weak_ptr。当然,您不只是随意查看两者中的一个,要替换哪一个取决于您的设计,并且您最终可能会同时替换它们(这完全取决于所有权语义)。但是,如果您替换(至少)其中一个,问题就解决了。

这同样适用于您设计中的所有参考周期

于 2013-07-02T12:25:48.430 回答