简体   繁体   English

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

[英]Composition in c++ with raw or smart pointer?

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. 其次,ID用于其他程序。

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. 它需要一个文件,其中包含所有顶点及其坐标的列表,以及所有边的列表及其两个顶点的ID。

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. 第三,我需要某种指针,因为顶点的id在运行时会发生变化,而边缘的源和目标顶点可能会变为。

(amongst other things some kind of cuts and slicing is performed) (其中包括进行某种切割和切片)

What Composition is 是什么组成


Composition (in UML terms) is an association when a given object is "a part" of another objects- ie it has the same lifetime and - what's most important and characteristic - does not exist / make sense on its own . 组合(以UML术语)是当给定对象是另一个对象的“一部分”时的关联 - 即它具有相同的生命周期 - 并且 - 最重要和特征 - 本身不存在/有意义

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: 在C或C ++中,实现组合的最佳方法是不使用任何指针:

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不适合这个问题


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. 然后,您希望每个边引用 N个顶点。

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, eg if you'd want to use the latter array as an index buffer for 3D rendering). 您甚至可以使用数组索引而不是指针作为替代(实际上它有其用途,例如,如果您想将后一个数组用作3D渲染的索引缓冲区)。 All depends on your needs. 一切都取决于您的需求。

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? 在上面,你想拥有顶点谁?

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 (eg, decide 0<=id<n , then you can have an array of size n ), and store the ids in the Edge rather than the pointers. 如果您担心安全性和边界检查等问题较长时间,请按其ID排序每个Vertex (例如,确定0<=id<n ,然后您可以使用大小为n的数组),并将ID存储在Edge而不是指针。 Then you can use an assert , or whatever, to check that ids are in the legal range. 然后,您可以使用assert或其他任何方法来检查ID是否在合法范围内。

It's a question of who owns the pointers. 这是谁拥有指针的问题。 If your Edge class owns them then you can use an auto_ptr. 如果您的Edge类拥有它们,那么您可以使用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. 但是,您说您的Vertex对象是在堆栈上分配的,因此在这种情况下不需要进行显式清理,因为当它们超出范围时它们将被删除。

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. 如果你想这样,请使用Boost的shared_ptr

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. 但看起来你可能正在进行CPU密集型图形处理,这是速度可能是一个重要因素的情况之一。 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. 注意:如果顶点有可能指向一个指向它的边缘,事情会变得更复杂 - 你需要对其中一个指针使用weak_ptr来避免循环引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM