我目前正在手动管理项目中对象的生命周期。我正在考虑切换到智能指针,特别是 tr1::shared_pointer 和 tr1::weak_ptr。但是,我看到了一些问题,并希望获得有关最佳实践的一些意见。
考虑下面的类图:
在此图中,粗箭头表示与所有权语义的关联(源负责删除一个或多个目标)。细箭头表示没有所有权的关联。
据我了解,实现与所有权语义关联的一种方法是使用 tr1::shared_ptr (或其集合)。其他关联可以使用 tr1::shared_ptr 或 tr1::weak_ptr 来实现。如果前者可能导致循环引用,则禁止前者,因为这会妨碍资源的正确释放。
如您所见,Edge 和 Side 类之间存在一圈关联。我可以通过使用 tr1::weak_ptrs 实现从 Edge 到 Side 的“左”和“右”关联来轻松打破这一点。但是,我更喜欢使用智能指针在代码中记录关联的所有权语义。所以我想将 shared_ptrs 仅用于图中粗箭头表示的关联,而将 weak_ptrs 用于其他所有内容。
现在我的第一个问题是:我应该像上面描述的那样自由地使用weak_ptrs,还是应该尽可能少地使用它们(只是为了避免循环引用)?
下一个问题是:假设我有一个计算一组顶点平均值的函数。进一步假设我已经实现了从多面体到它的顶点的关联,如下所示:
class Vertex;
class Polyhedron {
protected:
std::vector<std::tr1::shared_ptr<Vertex> > m_vertices;
};
并且我已经实现了从 Side 到它的 Vertices 的关联,如下所示:
class Vertex;
class Side {
protected:
std::vector<std::tr1::weak_ptr<Vertex> > m_vertices;
};
请注意,边的顶点集是多面体顶点集的子集。现在假设我有一个计算一组顶点平均值的函数。该函数当前声明如下:
const Vertex centerOfVertices(std::vector<Vertex*> vertices);
现在,如果我如上所述表示关联,如果我正确理解所有内容,我突然需要两个函数:
const Vertex centerOfVertices(std::vector<std::tr1::shared_ptr<Vertex> > vertices);
const Vertex centerOfVertices(std::vector<std::tr1::weak_ptr<Vertex> > vertices);
因为我无法在 shared_ptr 的向量和weak_ptr 的向量之间进行转换。这对我来说很有趣。我想知道我应该在这里采取什么方法来避免这种情况。