现代C ++对象关系

时间:2015-03-04 12:53:54

标签: c++ oop object smart-pointers

我使用struct Nodestruct Edge实现了图表,其中:

  • 每个Edge都有一个开头和结尾Node
  • 每个Node都会维护一个Edge个对象的列表,这个对象从它开始或结束

以下是一种可能的实施方式:

struct Node;

struct Edge {
  Node *st;
  Node *en;
  int some_data;
};

const int MAX_EDGES = 100;
struct Node {
  Edge *edges[MAX_EDGES];
  int some_data;
};

虽然上面的结构可以代表我想到的图形,但我想做的是"现代C ++"在满足以下要求的同时:

  1. 避免使用指针
  2. 使用std::vector Node::edges
  3. 能够将NodeEdge个对象存储在标准C ++容器中
  4. 在Modern C ++中如何完成?可以实现1-3的全部吗?

3 个答案:

答案 0 :(得分:8)

  
      
  1. 避免使用指针
  2.   

您可以使用std::shared_ptrstd::weak_ptr。只需决定是否希望节点拥有边缘,反之亦然。非拥有类型应使用weak_ptr(以避免循环)。

除非您的图表是非循环的,否则您可能仍需要注意所有权周期。

std::unique_ptr不是一个选项,因为节点和边之间没有一对一的关系,因此不能有任何给定对象的唯一所有者。

  
      
  1. 对Node :: edges
  2. 使用std :: vector   

没问题。将其设为std::vector<std::weak_ptr<Edge>>std::vector<std::shared_ptr<Edge>>(取决于边缘是否拥有节点,反之亦然)

  
      
  1. 能够将Node和Edge对象存储在标准C ++容器中
  2.   

没问题,只需确保您的类型可以安全地移动/复制而不会泄漏或损坏内存,即具有正确的复制/移动构造函数和赋值运算符。如果您使用上面建议的智能指针和std::vector,这将自动发生。

答案 1 :(得分:1)

Modern C ++避免将动态内存分配给原始指针。这是因为很容易忘记删除所述指针。虽然说使用原始指针作为对象的引用没有任何问题,但是你可以保证对象的生命周期将大于使用所述指针。

规则通常是:

  1. 如果对象拥有单一所有者,请使用std::unique_ptr
  2. 使用原始指针引用在1中创建的对象,前提是您可以保证对象的生命周期大于使用引用。
  3. 使用std::shared_ptr作为参考计数对象
  4. 当您不想增加引荐计数时,使用std::weak_ptr来引用引用计数对象。
  5. 所以在你的情况下,如果Edge拥有Node s然后使用std::unique_ptr,如果没有,则保留原始指针。 在Node课程中,如果Node拥有Edges,则使用std::vector<Edge>,否则请使用std::vector<Edge*>,但链接您的Edges可能更有效1}}在他们自己的侵入链表中。

    在复杂的图形上做了一些工作后,可能会将所有NodeEdge es分配到图形外部的向量中,然后仅使用图形内部的原始指针在内部引用它们。记住内存分配很慢所以你做的越少,你的算法就会越快。

答案 2 :(得分:0)

  1. 使用std :: shared_ptr或std :: unique_ptr
  2. 我不认为矢量是一个正确的选择,因为图形通常不是线性的(通常来说,在大多数情况下,你可以像堆一样线性化它)
  3. 没有标准的&#39;一般用途&#39;容器,但你可以在这里使用模板来实现一致性
  4. 例如,您的Element类看起来像这样:

    template <class T>
    struct Elem {
      std::shared_ptr<Node> st , en;
      T some_data;
    };
    
    谈到现代C ++,我不认为在这里鼓励结构,你可以封装数据