我想做的一个小例子。
我有一个(堆栈分配的)顶点列表
class Vertex {
int id;
double x;
double y;
double z;
};
并想要创建边缘列表
class Edge {
int id;
Vertex * source;
Vertex * target;
};
有两个指向其源和目标顶点的指针。
通常我会在这里找一个参考,但我希望能够在运行时更改源或目标顶点,所以我需要某种指针类型。
所以我的问题是:是否有一个智能指针在这里很有用,或者我应该只使用上面的普通指针?
修改
解决答案中出现的一些问题:
首先,列表应该拥有顶点,这就是它们在堆栈中的原因。
其次,ID用于其他程序。
它需要一个文件,其中包含所有顶点及其坐标的列表,以及所有边的列表及其两个顶点的ID。
第三,我需要某种指针,因为顶点的id在运行时会发生变化,而边缘的源顶点和目标顶点可能会变为。
(除此之外还会进行某种切割和切片)
答案 0 :(得分:7)
组合(用UML术语)是当给定对象是另一个对象的“一部分”时的关联 - 即它具有相同的生命周期 - 以及 - 最重要和最具特色的 - 不存在/有意义。
根据此描述,构图不是我们想要达到的目标 - 请参阅第二部分。
在C或C ++中,实现组合的最佳方法是不使用任何指针:
class Edge {
int id;
Vertex source;
Vertex target;
};
这种方法在内存使用方面是最好的(整个对象的一个内存块以及复合对象),也可能是效率。当你需要合成时 - 去寻找这个解决方案。
组成意味着一些结果:
在您的数据模型中,您有单独的:
两者都可能是堆栈分配的(但这并不重要)。
然后你希望每条边引用到N个顶点。
边缘不拥有它们 - 它只会引用它们。因此,无论是组合,还是智能指针(设计用于引入某种所有权关联)都不是您想要的,因为设计说顶点由顶点数组拥有,而不是由边< / em>的
所以选择一个简单的指针。
您甚至可以使用数组索引而不是指针作为替代(确实有其用途,例如,如果您想将后一个数组用作3D渲染的索引缓冲区)。一切都取决于您的需求。
答案 1 :(得分:1)
一般来说,智能指针是“智能的”,因为它们处理所涉及的所有权问题。在上面,你想要拥有顶点?
答案 2 :(得分:1)
使用普通指针。如果指向的对象被分配在堆栈上,智能指针就不会有用了。
如果您担心安全和边界检查的时间较长等等,请按其ID Vertex
命令每个0<=id<n
,然后您可以拥有一个大小为{{{1}的数组。 1}}),并将id存储在n
而不是指针中。然后,您可以使用Edge
或其他任何内容来检查ID是否在合法范围内。
答案 3 :(得分:0)
这是谁拥有指针的问题。如果您的Edge类拥有它们,那么您可以使用auto_ptr。但是,您说您的Vertex对象是在堆栈上分配的,因此在这种情况下不需要进行显式清理,因为当它们超出范围时它们将被删除。
答案 4 :(得分:0)
这是通常的权衡:智能指针会更安全但更慢。如果你想这样,请使用Boost's shared_ptr
。
对于“业务逻辑”,我强烈建议使用智能指针。但看起来你可能正在进行CPU密集型图形处理,这是速度可能是一个重要因素的情况之一。所以我建议:
//typedef Vertex *VertexPtr
typedef shared_ptr<Vertex> VertexPtr
class Edge {
int id;
VertexPtr source;
VertexPtr target;
};
使用它进行调试,并在一切正常工作时切换//
。
注意:如果顶点有可能指向指向它的边缘,事情会变得更复杂 - 您需要对其中一个指针使用weak_ptr
以避免循环引用。