删除任一个时,删除由两个shared_pointer实例管理的对象

时间:2016-03-08 23:32:28

标签: c++ pointers

我有一个由NodeEdge类表示的有向图模型。每个Node对象都保存指向其所有传出和传入边的指针,每个Edge对象保存指向其原点和结尾(Node对象)的指针。

class Model
{
public:
    ~Model() 
    {
        for(Node *node : nodes)
            delete node;
    }

    QVector<Node*> nodes;
};

class Node
{
    public:
    ~Node
    {
            for(Edge *edge : from)
            {
                if(edge)
                {
                    edge->to->to.replace(edge, nullptr);      
                    delete edge;
                }
            }

            for(Edge *edge : to)
            {
                if(edge)
                {
                    edge->from->from.replace(edge, nullptr);
                    delete edge;
                }
            }
    }

    QVector<Edge*> from;
    QVector<Edge*> to;
};

class Edge
{
public:
    Node *from;
    Node *to;
};

到目前为止,我已经使用这样的原始指针实现了它。它相当复杂,并且当节点被删除时涉及从边缘的另一侧(对于每个边缘)手动移除指针。我宁愿使用智能指针使它更安全和更清洁。

然而,我需要为双方删除边缘(并使另一边的指针无效)这一事实使其成为问题。如果我使用共享指针,则边缘永远不会被删除(即使另一边消失,剩余的引用也将保持有效)。如果我使用弱指针,我反过来需要将共享指针存储在其他地方,这将再次变得更加复杂,因为我需要查找它并在任何一方被删除时摆脱它。

我需要的是一个&#34; smart&#34;指针将跟踪指针对象(如共享指针),但在其内部计数器降为1(而不是0)时删除其指针,以使其自身无效(如弱指针)而不会超出范围。

我应该自己写还是有其他解决方案?

2 个答案:

答案 0 :(得分:1)

如果该实例被删除,您希望能够执行的操作是使Node实例的所有指针无效。这意味着你想要一个自我所有权的概念。因此,指向Node的所有指针都应该是指向由Model(或者Node本身)管理的共享指针的弱指针。

可以使每个Node只有指向相邻节点的弱指针。 Edge可以根据需要按需制作,而Edge也只能包含弱指针。

答案 1 :(得分:1)

<强>节点

每个边缘至少由两个节点引用。如果没有节点引用边缘,则此边缘无用且可以删除。这表明从节点到边缘的指针应该是shared_ptr<Edge>

模型中的指针向量应该是shared_ptr<Node>

<强>边

仅当源节点和目标节点存在时,边缘才可存在,但节点可以不存在边缘。这表明节点边缘的指针应为weak_ptr<Node> from, to;

您始终可以使用from.expired()检查是否删除了fromto个节点。但是你没有办法绕过正确的方法来移除边缘:从两侧移除它的指针,在这种情况下,当不再需要时会触发边缘的破坏。