我目前正在手动管理项目中对象的生命周期。我正在考虑切换到智能指针,特别是tr1::shared_pointer和tr1::weak_ptr。然而,我看到了一些问题,并希望获得一些关于最佳实践的意见。
考虑下面的类图:

在此图中,粗箭头表示与所有权语义的关联(源负责删除一个或多个目标)。细箭头表示没有所有权的关联。
据我所知,实现与所有权语义关联的一种方法是使用tr1::shared_ptr (或其集合)。其他关联可以使用tr1::shared_ptr或tr1::weak_ptr实现。如果前者可能导致循环引用,则禁止前者,因为这将阻止资源的适当释放。
正如您所看到的,在类Edge和Side之间有一个关联的圆圈。我可以通过使用tr1::weak_ptrs实现边到边的“左”和“右”关联来很容易地打破这一点。但是,我更喜欢使用智能指针在代码中记录关联的所有权语义。因此,我只想对图中粗箭头表示的关联使用shared_ptrs,而对其他所有内容使用weak_ptrs。
现在我的第一个问题是:我应该像上面描述的那样自由地使用weak_ptrs,还是应该尽可能少地使用它们(只为了避免循环引用)?
下一个问题是:假设我有一个计算一组顶点的平均值的函数。进一步假设我已经实现了从多面体到其顶点的关联,如下所示:
class Vertex;
class Polyhedron {
protected:
std::vector<std::tr1::shared_ptr<Vertex> > m_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向量之间进行转换。我觉得这味道很奇怪。我想知道在这里我应该采取什么方法来避免这种情况。
发布于 2012-06-13 21:55:15
但是,我更喜欢使用智能指针在代码中记录关联的所有权语义。
这是你应该做的。毕竟,这就是他们完美的表达方式。
所以我只想对图中用粗箭头表示的关联使用shared_ptrs,对其他所有东西都使用weak_ptrs。
去做吧,有一个警告:你的所有权看起来一点也不像共享所有权,它是简单的、唯一的所有权。因此,这里适当的智能指针不是shared_ptr,而是std::unique_ptr,弱指针就是原始指针。
现在,如果我像上面那样表示关联,我突然需要两个函数…
是。好吧,或者你使用模板。
或者,由于函数实际上对共享所有权不感兴趣,您可以将原始指针传递给它,但这当然意味着首先从您的结构中获取原始指针,这需要为客户端添加一个步骤,这可能对接口不好。
发布于 2012-06-14 00:02:09
使用共享指针似乎是明智的,特别是你可能会发现顶点等可以在多面体之间共享。
要将弱指针向量转换为共享指针向量,请使用显式构造函数:
centerOfVertices(std::vector<std::tr1::shared_ptr<Vertex> >(vertices.begin(), vertices.end()));发布于 2012-06-13 22:04:16
当然,您也可以使用shared_ptr进行循环引用。在一些罕见的情况下,这实际上是有意义的。但是,一旦使用完对象,就必须注意打破这个循环。
https://stackoverflow.com/questions/11015908
复制相似问题