C++11 C+中图形表示(顶点邻域)的智能指针+;11

C++11 C+中图形表示(顶点邻域)的智能指针+;11,c++11,graph,shared-ptr,unique-ptr,adjacency-list,C++11,Graph,Shared Ptr,Unique Ptr,Adjacency List,我想知道如何正确使用C++11智能指针进行图形表示 假设有一个包含所有顶点向量的图结构。此外,您还有一个顶点的结构/类。该顶点包含其所有邻居的向量(邻接列表) 我的问题是:我应该使用哪种类型的指针/智能指针来表示这个图 我读到,对于二叉树,对于父节点,应该使用原始指针。因为节点不拥有其父节点。二叉树的子节点可以用std::unique_ptr表示,因为节点拥有子节点的所有权 但在一个图中,多个节点可能有共同的邻居。那么,我应该为此使用std::shared\u ptr吗?还是应该使用原始指针?您

我想知道如何正确使用C++11智能指针进行图形表示

假设有一个包含所有顶点向量的图结构。此外,您还有一个顶点的结构/类。该顶点包含其所有邻居的向量(邻接列表)

我的问题是:我应该使用哪种类型的指针/智能指针来表示这个图

我读到,对于二叉树,对于父节点,应该使用原始指针。因为节点不拥有其父节点。二叉树的子节点可以用std::unique_ptr表示,因为节点拥有子节点的所有权


但在一个图中,多个节点可能有共同的邻居。那么,我应该为此使用std::shared\u ptr吗?还是应该使用原始指针?

您必须首先设计节点(或边缘)所有权策略

例如,在您站点的二叉树示例中,父节点拥有其子节点,但不拥有其父节点。这种设计确保树中的每个节点都由另一个节点拥有,根节点除外,您可以对根节点进行特殊处理。由于在本例中,每个节点只有一个所有者(其父节点),
unique\u ptr
可用于建模此关系。同样在本例中,从子链接到父链接是非所有者链接,因此不能使用所有者智能指针建模

在二叉树示例中,您拥有的图是非循环的、有向的,每个节点只指向一次(通过拥有指针)

在更复杂的示例中,图可能是非循环的、有向的,但节点可以指向多次。这样的图可以使用
shared\u ptr
对指向的链接进行建模,因为这些链接共享指向对象的所有权

然而,我们必须小心。一旦图形变为循环,则
shared_ptr
就不能再专门使用。任何时候设置所有权循环:

A owns B which owns C which owns A
然后设置内存泄漏。可以使用
shared\u ptr
unique\u ptr
创建此类循环。但在实践中,使用
shared\u ptr
时,周期往往更频繁,这可能是因为所有权图本质上比
unique\u ptr
更复杂

shared\u ptr
包含一个用于打破循环所有权模式的帮助器类:
weak\u ptr
。这可用于设置以下内容:

A owns B which owns C which has a (non-owning) weak_ptr to A
如果图形是无向的,并且您使用以下内容对节点A和B建模:

A points to B and B points to A
然后立即设置一个循环,因此这两个指针都不能拥有指针。在这种情况下,您将不得不设计什么拥有什么。也许一段完全独立的代码可以拥有所有的节点,所有的边都可以用不拥有的指针表示。也许可以将图划分为一组非循环有向边(表示拥有指针)和所有其他边(非拥有指针)。实际上,这正是我们对二叉树所做的——拥有子指针和不拥有父指针


无论您的设计是什么,一旦完成,您的设计将引导您确定
shared_ptr
和/或
unique_ptr
是否是实现您的设计的合适工具。如果某个东西总是被唯一地拥有,
unique\u ptr
是一个可行的选择。如果某些东西需要由其他几个实体拥有,
shared\u ptr
可能是正确的工具(当然不是
unique\u ptr
)。如果
shared\u ptr
所有权图包含循环,则可以通过将其中一些链接替换为
weak\u ptr
来破坏这些循环。如果您未能检测并中断所有权图中的周期,这些周期将导致内存泄漏。

@HerbSutter刚刚在其网站上发布,CPPCON16上公布的解决方案似乎总体上不起作用,如果删除了节点的所有共享父节点,但仍然存在来自其他节点的弱ptr引用,该怎么办。在这种情况下,节点将被无意中删除。