我有一个由 Node
和 Edge
类表示的有向图模型。每个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;
};
到目前为止,我已经使用这样的原始指针实现了它。它相当复杂,并且涉及在删除节点时从边缘的另一侧(对于每条边缘)手动删除指针。我宁愿使用智能指针来使其更加安全和干净。
然而,事实上我需要删除两侧的边缘(并使另一侧的指针无效),这使得它成为问题。如果我使用共享指针,则边缘永远不会被删除(即使另一侧消失,剩余的引用也将保持有效)。如果我使用弱指针,我又需要将共享指针存储在其他地方,这将再次变得更加复杂,因为每当任何一方被删除时我都需要查找它并删除它。
我需要的是一个“智能”指针,它将跟踪被指针(如共享指针),但当其内部计数器降至 1(而不是 0)时删除其被指针,从而使其自身失效(如弱指针)不超出范围。
我应该自己写还是有其他解决方案?
最佳答案
节点
每条边至少由两个节点引用。如果没有节点引用一条边,则该边无用,可以删除。这表明从节点到边的指针应该是 shared_ptr<Edge>
。
模型中的指针 vector 应该是 shared_ptr<Node>
边缘
只有源节点和目标节点存在时,边才能存在,但没有边的节点也可以存在。这表明边中指向节点的指针应该是 weak_ptr<Node> from, to
;
您可以随时检查 from
是否或to
节点已被删除 from.expired()
。但是您无法找到删除边缘的正确方法:从两侧删除其指针,在这种情况下,当不再需要时会触发边缘的销毁。
关于c++ - 当两个shared_pointer实例被删除时,删除由两个shared_pointer实例管理的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35880154/