c++ 中的构图使用原始指针或智能指针?

发布于 2024-10-07 07:19:29 字数 637 浏览 5 评论 0 原文

我想做的一个小例子。

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

class Vertex {

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

,想要创建一个边列表

class Edge {

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

,其中两个指针指向其源顶点和目标顶点。

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

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

编辑

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

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

其次,这些 ID 是用于其他程序的。

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

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

(除其他外,还执行某种切割和切片)

A little example of what I want to do.

I have a list of (stack allocated) vertices

class Vertex {

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

and want to create a list of edges

class Edge {

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

with two pointers to its source and target vertex.

Normally I would go for a reference here, but I want to be able to change the source or target vertex during runtime, so I need some kind of pointer type.

So my question: is there a smart pointer which would be useful here or should I just use a normal pointer as above?

Edit

Addressing some points, which came up in the answers:

First, the list should own the vertices, which is why they are on the stack.

Second, the ids are for an other program.

It needs a file with a list of all vertices and their coordinates, and a list of all edges and the ids of its two vertices.

Third, I need some kind of pointer, because the ids of the vertices change during runtime and the source and target vertex of a edge could change to.

(amongst other things some kind of cuts and slicing is performed)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

罪歌 2024-10-14 07:19:29

什么是组合


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

根据这个描述,组合不是我们想要实现的 - 请参阅第二部分。

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

class Edge {

    int id;
    Vertex source;
    Vertex target;
};

这种方法在以下方面是最好的:内存使用(整个对象以及复合对象的一个​​内存块)以及可能的效率。当您需要构图时,请选择此解决方案。

为什么组合不适合这个问题


组合意味着一些后果:

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

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

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

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

然后您希望每条边引用 N 个顶点。

边缘并不拥有它们——它只是引用它们。因此,组合或智能指针(旨在引入某种所有权关联)都不是您想要的,因为设计表明顶点由顶点数组拥有,而不是由边拥有< /em>。

所以选择一个普通的指针。

您甚至可以使用数组索引代替指针作为替代方案(这确实有其用途,例如,如果您想使用后一个数组作为 3D 渲染的索引缓冲区)。一切都取决于您的需求。

What Composition is


Composition (in UML terms) is an association when a given object is "a part" of another objects- i.e. it has the same lifetime and - what's most important and characteristic - does not exist / make sense on its own.

According to this description, composition is not what we want to achieve - see the second part.

In C or C++, the best way to implement composition is without using any pointers:

class Edge {

    int id;
    Vertex source;
    Vertex target;
};

This approach is best in terms of memory usage (one memory block for the whole object along with composite objects) and probably efficiency too. When you need composition - go for this solution.

Why Composition isn't suitable for this problem


Composition implies some consequnces:

  • The composed objects don't exist on their own,
  • Their association with the composite object is permanent during that object's lifetime.

In your data model, you have separate:

  • Array of vertices (independent),
  • Array of edges.

Both possibly stack-allocated (but that's not really important).

Then you want each edge to refer to N vertices.

The edge does NOT own them - it only does refer to them. So neither composition, nor a smart pointer (which is designed to introduce some kind of ownership association) is not what you want here, because the design says that the vertices are owned by the array of vertices, not by the edges.

So go for a plain pointer.

You could even use array indices instead of pointers as an alternative (which indeed has its uses, e.g. if you'd want to use the latter array as an index buffer for 3D rendering). All depends on your needs.

弄潮 2024-10-14 07:19:29

一般来说,智能指针之所以“智能”,是因为它们处理所涉及的所有权问题。在上面,您希望谁拥有顶点?

Generally speaking, smart pointers are "smart" because they deal with the ownership issues involved. In the above, who do you want to own the vertices?

海的爱人是光 2024-10-14 07:19:29

使用普通指针。如果指向的对象是在堆栈上分配的,那么智能指针就没有那么有用了。

如果您从长远来看担心安全性和边界检查等问题,请按每个 Vertex 的 id 排序(例如,决定 0<=id,然后您可以有一个大小为 n 的数组),并将 id 存储在 Edge 而不是指针中。然后您可以使用 assert 或其他方式来检查 id 是否在合法范围内。

Use a normal pointer. If the pointed-at objects are allocated on the stack, a smart pointer won't be all that helpful.

If you are concerned in the longer run about safety and bounds checking and so on, order each Vertex by its id (e.g., decide 0<=id<n, then you can have an array of size n), and store the ids in the Edge rather than the pointers. Then you can use an assert, or whatever, to check that ids are in the legal range.

烟火散人牵绊 2024-10-14 07:19:29

这是谁拥有指针的问题。如果您的 Edge 类拥有它们,那么您可以使用 auto_ptr。但是,您说您的 Vertex 对象是在堆栈上分配的,因此在这种情况下不需要显式清理,因为当它们超出范围时它们将被删除。

It's a question of who owns the pointers. If your Edge class owns them then you can use an auto_ptr. However, you say that your Vertex objects are allocated on the stack so there's no real need for explicit clean-up in this scenario, as they'll be deleted when they go out of scope.

情话墙 2024-10-14 07:19:29

这是通常的权衡:智能指针会更安全但速度更慢。使用 Boost 的 shared_ptr 如果你想走那条路。

对于“业务逻辑”,我强烈提倡使用智能指针。但看起来您可能正在进行 CPU 密集型图形处理,这就是速度可能是重要因素的情况之一。所以我建议:

//typedef Vertex *VertexPtr
typedef shared_ptr<Vertex> VertexPtr

class Edge {
    int id;
    VertexPtr source;
    VertexPtr target;
};

使用它进行调试,并在一切正常时切换 // 以提高速度。

注意:如果顶点有可能指向指向它的边,事情就会变得更加复杂 - 您将需要对其中一个指针使用 weak_ptr 以避免循环引用。

It's the usual tradeoff: a smart pointer will be safer but slower. Use Boost's shared_ptr if you want to go that way.

For "business logic", I would strongly advocate using smart pointers. But it looks like you may be doing CPU-intensive graphics processing, which is one of the cases where speed may be an important factor. So I suggest:

//typedef Vertex *VertexPtr
typedef shared_ptr<Vertex> VertexPtr

class Edge {
    int id;
    VertexPtr source;
    VertexPtr target;
};

Use this for debugging, and switch the // when everything's working for a speed boost.

NOTE: If there is any possibility that a vertex may point back to an edge that points to it, things get more complicated -- you will need to use weak_ptr for one of the pointers to avoid circular references.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文