首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用智能指针建模所有权的含义

使用智能指针建模所有权的含义
EN

Stack Overflow用户
提问于 2012-06-13 21:29:14
回答 3查看 307关注 0票数 4

我目前正在手动管理项目中对象的生命周期。我正在考虑切换到智能指针,特别是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,还是应该尽可能少地使用它们(只为了避免循环引用)?

下一个问题是:假设我有一个计算一组顶点的平均值的函数。进一步假设我已经实现了从多面体到其顶点的关联,如下所示:

代码语言:javascript
复制
class Vertex;
class Polyhedron {
protected:
    std::vector<std::tr1::shared_ptr<Vertex> > m_vertices;
};

并且我已经实现了从一边到顶点的关联,如下所示:

代码语言:javascript
复制
class Vertex;
class Side {
protected:
    std::vector<std::tr1::weak_ptr<Vertex> > m_vertices;
};

请注意,边的顶点集是多面体的顶点集的子集。现在假设我有一个计算一组顶点的平均值的函数。该函数当前的声明方式如下:

代码语言:javascript
复制
const Vertex centerOfVertices(std::vector<Vertex*> vertices);

现在,如果我像上面那样表示关联,如果我正确理解了所有内容,我突然需要两个函数:

代码语言:javascript
复制
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向量之间进行转换。我觉得这味道很奇怪。我想知道在这里我应该采取什么方法来避免这种情况。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-06-13 21:55:15

但是,我更喜欢使用智能指针在代码中记录关联的所有权语义。

这是你应该做的。毕竟,这就是他们完美的表达方式。

所以我只想对图中用粗箭头表示的关联使用shared_ptrs,对其他所有东西都使用weak_ptrs。

去做吧,有一个警告:你的所有权看起来一点也不像共享所有权,它是简单的、唯一的所有权。因此,这里适当的智能指针不是shared_ptr,而是std::unique_ptr,弱指针就是原始指针。

现在,如果我像上面那样表示关联,我突然需要两个函数…

是。好吧,或者你使用模板。

或者,由于函数实际上对共享所有权不感兴趣,您可以将原始指针传递给它,但这当然意味着首先从您的结构中获取原始指针,这需要为客户端添加一个步骤,这可能对接口不好。

票数 1
EN

Stack Overflow用户

发布于 2012-06-14 00:02:09

使用共享指针似乎是明智的,特别是你可能会发现顶点等可以在多面体之间共享。

要将弱指针向量转换为共享指针向量,请使用显式构造函数:

代码语言:javascript
复制
centerOfVertices(std::vector<std::tr1::shared_ptr<Vertex> >(vertices.begin(), vertices.end()));
票数 1
EN

Stack Overflow用户

发布于 2012-06-13 22:04:16

当然,您也可以使用shared_ptr进行循环引用。在一些罕见的情况下,这实际上是有意义的。但是,一旦使用完对象,就必须注意打破这个循环。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11015908

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档