Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 现代C++;对象关系_C++_Oop_Object_Smart Pointers - Fatal编程技术网

C++ 现代C++;对象关系

C++ 现代C++;对象关系,c++,oop,object,smart-pointers,C++,Oop,Object,Smart Pointers,我使用struct节点和struct边实现了一个图,其中: 每个边都有一个开始和一个结束节点 每个节点维护从其开始或结束的边对象列表 以下是一种可能的实施方式: 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; }; 虽然上面的结

我使用
struct节点和
struct边实现了一个图,其中:

  • 每个
    都有一个开始和一个结束
    节点
  • 每个
    节点
    维护从其开始或结束的
    对象列表
以下是一种可能的实施方式:

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++”的方式来实现它,同时满足以下要求:

  • 避免使用指针
  • 对于
    节点::边
  • 能够存储标准C++容器中的<代码>节点<代码>和<代码>边缘>代码>对象 <>这是如何在现代C++中完成的?所有的1-3都能实现吗

  • 通过使用std::shared\u ptr或std::unique\u ptr
  • 我认为向量在这里不是一个正确的选择,因为一个图通常不是线性的(通常来说,在大多数情况下,你不能像用堆那样线性化它)
  • 没有标准的“通用”容器,但您可以在此处使用模板来实现通用性
  • 例如,您的元素类可以如下所示:

    template <class T>
    struct Elem {
      std::shared_ptr<Node> st , en;
      T some_data;
    };
    
    模板
    结构元素{
    std::共享ptr st,en;
    T一些_数据;
    };
    
    关于现代C++,我认为这里不鼓励结构,你应该封装你的数据< /p>
  • 避免使用指针
  • 您可以为此使用
    std::shared_ptr
    std::weak_ptr
    。只需确定节点是否拥有边,反之亦然。非所有者类型应使用
    弱\u ptr
    (以避免循环)

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

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

  • 对节点::边使用std::向量
  • 没问题。将其设置为
    std::vector
    std::vector
    (取决于边是否拥有节点,反之亦然)

    能够在标准C++容器中存储节点和边缘对象
    没问题,只要确保您的类型可以安全地移动/复制,而不会泄漏或损坏内存,即具有正确的复制/移动构造函数和赋值运算符。如果你使用智能指针和代码> STD::向量< /代码>,这将自动发生。如

    < P>现代C++避免将动态内存分配给原始指针。这是因为很容易忘记删除所说的指针。尽管如此,使用原始指针作为对象的引用并没有错,但前提是您可以保证对象的生存期将大于使用所述指针的时间

    这些规则一般是:

  • 如果对象只有一个所有者,请使用
    std::unique_ptr
  • 使用原始指针引用在1中创建的对象。前提是您可以保证对象的生存期大于引用的使用期
  • 对引用计数对象使用
    std::shared_ptr
  • 当您不想增加引用计数时,使用
    std::weak_ptr
    引用引用计数的对象
  • 因此,在您的情况下,如果
    边缘
    拥有
    节点
    s,则使用
    std::unique\u ptr
    ,如果没有,则保留原始指针。 在您的
    节点
    类中,如果
    节点
    拥有
    请使用
    std::vector
    否则请使用
    std::vector
    ,尽管将
    链接到它们自己的入侵链接列表中可能更有效


    在复杂图形上做了一些工作后,可能需要在图形外部的向量中分配所有
    节点和
    边,然后仅使用图形内部的原始指针在内部引用它们。记住内存分配很慢,所以你做的越少,你的算法就会越快 STD::List< <代码>,而不是<代码> STD::vector < /代码> .@ NeXT,为什么?将边插入节点列表的起始位置还是中间位置?是否合并或拼接边缘列表?链表看起来像什么?@Cyber对于我的特殊情况,我不需要快速插入。所以,
    std::list
    std::vector
    为我计算出同样的结果。避免使用“裸”或“原始”指针,因为“智能”指针(如std::shared_ptr、std::weak_ptr等)在概念上仍然是指针。
    unique_ptr
    很难正确,因为每个边都由两个节点“拥有”,或者每个节点都可以由多个边“拥有”
    std::vector
    是通用容器,除非您需要另一个容器的元素稳定性/迭代器无效规则,否则应首选它。模板是否适合解决此问题?他想处理几个类,而不是抽象这些类将包含的类型。一条边正好与两个节点相关联,因此不能在单个节点内通过值存储在
    std::vector
    。类似地,可以将多条边与给定节点关联,因此不能让所有这些边都拥有
    std::unique\u ptr
    。如果节点拥有边,反之亦然,则可以使用
    shared_ptr
    weak_ptr
    管理图形外部的所有所有权。