cfa*_*771 10 c++ shared-ptr directed-acyclic-graphs c++11
我有一个由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一样安全.什么时候不应该,(因此它比原始的C++指针更好)和std :: find()可以直接使用,因为与weak_ptr不同,shared_ptr可以被解引用.
这里是否有"更好"的设计,或者这是一个特定情况的问题,具体取决于例如,如果我执行weak_ptr :: lock()的额外操作或者冒险难以发现错误,这有多重要?
Arn*_*rtz 12
正如你自己所说的那样,shared_ptr在两个方向上使用都会创建创建内存泄漏并且很难找到和破坏的圆圈 - 你将失去(几乎)shared_ptr提供的所有好处.所以weak_ptr它应该是.
你说你的算法必须锁定weak_ptr- 我不同意.算法必须shared_ptr从节点获取父节点.节点的任务是锁定父节点weak_ptr并返回结果,正确设置为父节点或NULL.
它是一个实现细节,节点将父母存储为shared_ptr或weak_ptr.仅shared_ptr通过向任何客户端提供s来封装该细节.
class Node
{
/* ... */
std::weak_ptr<Node> parent;
public:
std::shared_ptr<Node> getParent()
{
return parent.lock();
}
};
Run Code Online (Sandbox Code Playgroud)
编辑: 当然,如果父母不止一个,概念上同样适用.
编辑2:
在评论中你提到迭代你父母列表的算法,因此有必要为每个算法编写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);
Run Code Online (Sandbox Code Playgroud)