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

C++ 使用智能指针建模所有权的含义,c++,C++,我目前正在手动管理项目中对象的生命周期。我正在考虑切换到智能指针,特别是tr1::shared_pointer和tr1::weak_ptr。然而,我发现了一些问题,希望获得一些关于最佳实践的信息 考虑以下类图: 在此图中,粗箭头表示与所有权语义的关联(源负责删除一个或多个目标)。细箭头表示没有所有权的关联 据我所知,实现所有权语义关联的一种方法是使用tr1::shared_ptr(或其集合)。其他关联可以使用tr1::shared_ptr或tr1::weak_ptr实现。如果前者可能导致循环引

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

考虑以下类图:

在此图中,粗箭头表示与所有权语义的关联(源负责删除一个或多个目标)。细箭头表示没有所有权的关联

据我所知,实现所有权语义关联的一种方法是使用tr1::shared_ptr(或其集合)。其他关联可以使用tr1::shared_ptr或tr1::weak_ptr实现。如果前者可能导致循环引用,则禁止前者,因为这将妨碍资源的适当释放

正如您所看到的,在类Edge和Side之间有一个关联圈。我可以通过使用tr1::weak_ptrs从边到边实现“左”和“右”关联来轻松打破这种局面。然而,我更喜欢使用智能指针在代码中记录关联的所有权语义。因此,我只想对图中由粗箭头表示的关联使用shared_ptr,对其他所有关联使用弱_ptr

现在我的第一个问题是:我应该像上面描述的那样自由地使用弱ptr,还是应该尽可能少地使用它们(只是为了避免循环引用)

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

class Vertex;
class Polyhedron {
protected:
    std::vector<std::tr1::shared_ptr<Vertex> > m_vertices;
};
类顶点;
类多面体{
受保护的:
std::向量m_顶点;
};
我已经实现了从侧面到顶点的关联,如下所示:

class Vertex;
class Side {
protected:
    std::vector<std::tr1::weak_ptr<Vertex> > m_vertices;
};
类顶点;
班边{
受保护的:
std::向量m_顶点;
};
请注意,边的顶点集是多面体顶点集的子集。现在让我们假设我有一个函数,计算一组顶点的平均值。函数当前声明如下:

const Vertex centerOfVertices(std::vector<Vertex*> vertices);
const顶点中心顶点(std::向量顶点);
现在,如果我像上面那样表示关联,如果我正确理解了所有内容,我突然需要两个函数:

const Vertex centerOfVertices(std::vector<std::tr1::shared_ptr<Vertex> > vertices);
const Vertex centerOfVertices(std::vector<std::tr1::weak_ptr<Vertex> > vertices);
const顶点中心顶点(std::向量顶点);
顶点的常数顶点中心(标准::向量顶点);
因为我不能在共享的向量和弱的向量之间转换。这闻起来很怪。我想知道我应该采取什么方法来避免这种情况

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

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

因此,我只想对图中由粗箭头表示的关联使用shared_ptr,对其他所有关联使用弱_ptr

去做吧,但有一点需要注意:你的所有权根本不像共享所有权,它是简单、独特的所有权。因此,这里合适的智能指针不是
shared_ptr
,而是
std::unique_ptr
,而弱指针将只是原始指针

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

对。或者你使用模板


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

您当然也可以将共享的ptr用于循环引用。在一些罕见的情况下,这是有意义的。但是,一旦处理完对象,就必须小心打破循环。

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

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

centerOfVertices(std::vector<std::tr1::shared_ptr<Vertex> >(vertices.begin(), vertices.end()));
顶点中心(std::vector(顶点.begin(),顶点.end());
什么意思“弱ptr不能转换为共享ptr”?在
weak_ptr
上调用
lock()
,它会给你一个
shared
我认为这会滥用
shared_ptr
,我没有仔细阅读,但它看起来并不是什么真正的共享所有权。使用
unique\u ptr
和原始指针,并保证您为系统提供(弱)原始指针,它们指向的对象在其作用域内有效。我想如果我知道
方面
代表什么,我会更好地理解这一点。它是指“脸”吗?@johndilling谢谢你指出这一点,我不知道。戴夫:那里没有一个主要实体对“所有者”或“家长”有严格的定义。在多面体相交的地方,它们可以共享顶点、边和顶点,或者边、顶点和面。我想这就是OP想要表现的。