c – weak_ptr VS shared_ptr在图形节点父列表中

我有一个由Graph和Node类实现的有向无环图.每个节点都有一个指向childern的指针列表和一个指向父节点的指针列表.我最近添加了父母,因为一些算法需要快速访问父列表,而且图形很小,每个节点只有很少的连接,所以没有内存问题.

子列表使用std :: shared_ptr,以便节点保存在内存中至少与父节点一样长.但是我不想让一个节点拥有它的父母,所以我使用weak_ptr作为父母的指针.

但是,算法存在问题.一个算法必须从weak_ptr创建一个新的shared_ptr,所以我不能直接使用operator ==,并且使用标准函数(如std :: find())需要编写一个名为my_weak_ptr.lock()的lambda函数,然后比较它到一些shared_ptr.

如果我切换到shared_ptr,代替节点删除代码中的任何小错误都可能导致内存泄漏.或者如果我有一个指向已经删除的节点的指针,代码将能够访问不应该存在的节点,因此发现一些错误可能会变得更加困难.但是使用shared_ptr与weak_ptr一样安全,因为不取消引用/删除/ etc.当不应该(因为它比原始的C指针好)和std :: find()可以直接使用,因为shared_ptr可以被取消引用,不像weak_ptr.

这里是否有“更好”的设计,或者这是具体情况的一个问题,这取决于例如如果我执行了weak_ptr :: lock()的额外操作,还是冒着难以发现的错误的风险呢?

解决方法

正如你所说,在双向使用shared_ptr将创建创建mem泄漏并且很难找到并破坏的圈子 – 您将丢失(几乎)shared_ptr提供的所有好处.所以weak_ptr应该是.

你说你的算法必须锁定weak_ptr – 我希望有所不同.这些算法必须从节点获取一个父类shared_ptr.锁定父级的weak_ptr是节点的任务,并将结果返回给父节点或NULL.

这是一个实现细节,节点将他们的父节点存储为shared_ptr或weak_ptr.仅通过向任何客户端提供shared_ptrs来封装该细节.

class Node
{
  /* ... */
  std::weak_ptr<Node> parent;
public:
  std::shared_ptr<Node> getParent()
  {
    return parent.lock();
  }
};

编辑:
当然,概念上同样适用,如果有不止一个父母.

EDIT2:
评论中,您提到的算法遍历您的父母列表,使得有必要为每个算法编写lambdas.如果您经常使用这些算法,请考虑编写一个自动锁定目标weak_ptr并返回一个shared_ptr的迭代器适配器:

template <class WPIterator>
struct LockTheWeakIterator
{
  //static_assert that WPiterator's value_type is some weak_ptr
  //typedef all those iterator typedefs
  typedef typename WPIterator::value_type::element_type element_type;

  shared_ptr<element_type> operator*()
  { return iter->lock(); }

  //provide all the other operators - boost.operators might help with that...

  WPIterator iter;
};

template <class IT>
LockTheWeakIterator<It> lockTheWeak(It iter);


//somewhere...
auto theParentIter = std::find_if(lockTheWeak(parents.begin()),lockTheWeak(parents.end()),whatIAmLookingFor);

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...