用原始或智能指针在c ++中组合?

时间:2010-12-11 14:29:51

标签: c++ oop smart-pointers composition

我想做的一个小例子。

我有一个(堆栈分配的)顶点列表

class Vertex {

    int id;
    double x;
    double y;
    double z;
};

并想要创建边缘列表

class Edge {

    int id;
    Vertex * source;
    Vertex * target;
};

有两个指向其源和目标顶点的指针。

通常我会在这里找一个参考,但我希望能够在运行时更改源或目标顶点,所以我需要某种指针类型。

所以我的问题是:是否有一个智能指针在这里很有用,或者我应该只使用上面的普通指针?

修改

解决答案中出现的一些问题:

首先,列表应该拥有顶点,这就是它们在堆栈中的原因。

其次,ID用于其他程序。

它需要一个文件,其中包含所有顶点及其坐标的列表,以及所有边的列表及其两个顶点的ID。

第三,我需要某种指针,因为顶点的id在运行时会发生变化,而边缘的源顶点和目标顶点可能会变为。

(除此之外还会进行某种切割和切片)

5 个答案:

答案 0 :(得分:7)

什么是


组合(用UML术语)是当给定对象是另一个对象的“一部分”时的关联 - 即它具有相同的生命周期 - 以及 - 最重要和最具特色的 - 不存在/有意义

根据此描述,构图不是我们想要达到的目标 - 请参阅第二部分。

在C或C ++中,实现组合的最佳方法是不使用任何指针:

class Edge {

    int id;
    Vertex source;
    Vertex target;
};

这种方法在内存使用方面是最好的(整个对象的一个​​内存块以及复合对象),也可能是效率。当你需要合成时 - 去寻找这个解决方案。

为什么Composition不适合此问题


组成意味着一些结果:

  • 组合对象本身不存在,
  • 在对象的生命周期内,它们与复合对象的关联是永久性的。

在您的数据模型中,您有单独的:

  • 顶点数组(独立),
  • 边缘数组。

两者都可能是堆栈分配的(但这并不重要)。

然后你希望每条边引用到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以避免循环引用。