数据模型、循环引用

发布于 2024-09-19 06:06:19 字数 1971 浏览 6 评论 0原文

我有以下用于存储经线和平行线的数据结构。

每个地图点存储:
A] 地理和空间坐标、制图扭曲等
B] 指向北/南/东/西节点的指针。

它允许存储点之间的关系,首先是它们与点之间的从属关系 子午线/平行...

 class Node2DCart 
 { 
     protected: 
             //Coordinates of the point 
             double lat; 
             double lon; 
             double lattrans; 
             double lontrans; 
             double x; 
             double y; 
 ..... 
             //Pointers to adjacent points in geographic network 
             Node2DCart *left; 
             Node2DCart *right; 
             Node2DCart *top; 
             Node2DCart *bottom; 
 ..... 
 }; 

子午线的数据结构存储子午线的经度,开始 经络的点和终点以及点数。

 class Meridian 
 { 
     private: 
             unsigned int points_count; 
             double longitude; 
             Node2DCart *start; 
             Node2DCart *end; 
 .... 
 }; 

所有点都存储在节点列表中:

typedef std::vector<Node2DCart*> TNodes2DCartList; 

class Node2DCartList 
{ 
     protected: 

             TNodes2DCartList nodes; 

     ... 
}; 

但是为 Node2DList 编写复制构造函数有一个大问题。 Meridian/Parallel 和 Node2Dlist 之间存在循环依赖关系。

复制构造函数使用 std::map 并用新的点和链接替换旧的点和链接,这不是实现问题...但是,从 Meridian 类开始/结束的指针指向旧 Node2DList 的点... Node2DList复制构造函数应该通知所有指向旧 Node2DList 点的经络,并将所有指针更改为新 Node2DList 点。该模型不允许这样做。

可能的解决方案是添加两个指向经线和平行点的指针所属:

 class Node2DCart 
 { 
     protected: 
             //Coordinates of the point 
             double lat; 
             double lon; 
             double lattrans; 
             double lontrans; 
             double x; 
             double y; 
 ..... 
             //Pointers to adjacent points in geographic network 
             Node2DCart *left; 
             Node2DCart *right; 
             Node2DCart *top; 
             Node2DCart *bottom; 
 ..... 
             Meridian *m;
             Parallel *p;
 };

恐怕这个提出的模型不好。两个班级之间仍然有循环参考...有人可以帮助我改进它吗?谢谢...

I have the following data structure for storing meridians and parallels.

Each cartographic point stores:
A] geographic and spatial coordinates, cartographic distortions, etc.
B] pointer to north/south/east/west node.

It allows to store relationships between points, first of all their affiliation to the
meridian/parallel...

 class Node2DCart 
 { 
     protected: 
             //Coordinates of the point 
             double lat; 
             double lon; 
             double lattrans; 
             double lontrans; 
             double x; 
             double y; 
 ..... 
             //Pointers to adjacent points in geographic network 
             Node2DCart *left; 
             Node2DCart *right; 
             Node2DCart *top; 
             Node2DCart *bottom; 
 ..... 
 }; 

Data structure for meridian stores longitude of the meridian, start
point and end point of the meridian and number of points.

 class Meridian 
 { 
     private: 
             unsigned int points_count; 
             double longitude; 
             Node2DCart *start; 
             Node2DCart *end; 
 .... 
 }; 

All points are stored in nodes list:

typedef std::vector<Node2DCart*> TNodes2DCartList; 

class Node2DCartList 
{ 
     protected: 

             TNodes2DCartList nodes; 

     ... 
}; 

But there is a big problem writing copy constructor for Node2DList. There is a cyclic dependency between Meridian/Parallel and Node2Dlist.

Copy constructor uses std::map and replaces old points and links with new, it is not an implementation problem... However pointers start/end from class Meridian point to points from old Node2DList... Node2DList copy constructor should have to notify all meridians pointed to old Node2DList points and change all pointers to new Node2DList points. This model does not allow it.

The possible solution would be adding two pointers pointing to meridian and parallel point belongs to:

 class Node2DCart 
 { 
     protected: 
             //Coordinates of the point 
             double lat; 
             double lon; 
             double lattrans; 
             double lontrans; 
             double x; 
             double y; 
 ..... 
             //Pointers to adjacent points in geographic network 
             Node2DCart *left; 
             Node2DCart *right; 
             Node2DCart *top; 
             Node2DCart *bottom; 
 ..... 
             Meridian *m;
             Parallel *p;
 };

I am afraid that this proposed model is not good. There are still cycling references between two classes... Would someone help me to improve it? Thanks...

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

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

发布评论

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

评论(2

十年不长 2024-09-26 06:06:28

在我看来,在某些情况下用索引替换指针的解决方案会很慢。

  • 如果我们不删除任何点,point_id将代表该点的索引,例如。节点[poin_id],就可以了。

  • 但是如果我们删除列表中的任何点,point_id将不代表其在列表中的索引。我们必须使用 std::find 并获取找到点的 point_id 。这显着降低了代码的速度...

  • 如果我们删除任何点,我们可以重新索引点列表以避免上述问题。但是我们不必忘记重新索引所有子午线开始/结束索引...但这需要一些时间并且与问题中的复制构造函数相同。而且我认为,使用复制构造函数影响另一个类的数据代表了不太合适的数据结构提议...

In my opininon, the solution replacing pointers with indices in some cases will be slow.

  • If we do not delete any point, point_id will represent index of he point, eg. nodes[poin_id], it is ok.

  • But if we delete any point of the list, point_id will not represent its index in the list. We will have to use std::find and get point_id of the found point. This significantly reduces the speed of the code...

  • If we delete any point we can reindex list of points to avoid problems mentioned above. But we do not have to forget to reindex all meridinans start / end indices... But it takes some time and does the same as the copy constructor in the question. And I think, that affecting the data of some class by another class using copy constructor represents not very suitable proposal of the data structure...

仅此而已 2024-09-26 06:06:26

有人可以帮助我改进它吗?

在这种情况下,我通常会采用这样的方法:

 typedef int node_id_t;
 enum { NODE_NULL = 0 };
 // or enum node_id_t { NODE_NULL=0 }; for strict typing.

 class Node2DCart 
 { 
     protected:
             node_id_t id;    // id of the node
             //Coordinates of the point 
             double lat; 
             double lon; 
             double lattrans; 
             double lontrans; 
             double x; 
             double y; 
 ..... 
             //Pointers to adjacent points in geographic network 
             node_id_t left;
             node_id_t right; 
             node_id_t top; 
             node_id_t bottom; 
 ..... 
 };

 class Meridian
 {
     private:
             unsigned int points_count;
             double longitude;
             node_id_t start;
             node_id_t end;
 .... 
 };

 /* ... */

 std::vector<Node2DCart *> node_registry;

 // during initialization:
 node_registry.push_back( NULL );
 // to reserve 0th element to denote the NULL pointer

 Node2DCart *
 GetNode(node_id_t id)
 {
    // placeholder of the id range check
    return node_registry[id];
 };

 node_id_t
 AddNode(Node2DCart *n)
 {
    node_registry.push_back(n);
    return node_id_t(node_registry.size()-1);
 };

然后使用数字 node_id_t 而不是 Node2DCart *。还可以放入 std::set (或 std::map,在 AddNode() 中更新/测试)以确保所有 Node2DCart 对象都是唯一的,如果不是,则重用现有对象的 id。

本质上是一种寻址方案,为每个节点提供唯一的全局标识符。不是最好/最简单的解决方案,具有全局容器,但不止一次帮助了我。特别是为了避免内存泄漏并确保彻底销毁相互依赖对象的整个层次结构。

除了 typedef int node_id_t 之外,还可以使用 struct node_id_t { int id; }; 和重载转换运算符以简化节点 ID 查找。

Would someone help me to improve it?

In such cases I generally resort to something like this:

 typedef int node_id_t;
 enum { NODE_NULL = 0 };
 // or enum node_id_t { NODE_NULL=0 }; for strict typing.

 class Node2DCart 
 { 
     protected:
             node_id_t id;    // id of the node
             //Coordinates of the point 
             double lat; 
             double lon; 
             double lattrans; 
             double lontrans; 
             double x; 
             double y; 
 ..... 
             //Pointers to adjacent points in geographic network 
             node_id_t left;
             node_id_t right; 
             node_id_t top; 
             node_id_t bottom; 
 ..... 
 };

 class Meridian
 {
     private:
             unsigned int points_count;
             double longitude;
             node_id_t start;
             node_id_t end;
 .... 
 };

 /* ... */

 std::vector<Node2DCart *> node_registry;

 // during initialization:
 node_registry.push_back( NULL );
 // to reserve 0th element to denote the NULL pointer

 Node2DCart *
 GetNode(node_id_t id)
 {
    // placeholder of the id range check
    return node_registry[id];
 };

 node_id_t
 AddNode(Node2DCart *n)
 {
    node_registry.push_back(n);
    return node_id_t(node_registry.size()-1);
 };

And then use the numeric node_id_t instead of Node2DCart *. One can also throw in a std::set (or std::map, updated/tested in the AddNode()) to ensure that all the Node2DCart objects are unique and if not reuse id of the existing object.

Essentially an addressing scheme, providing each node with a unique global identifier. Not the nicest/easiest solution, with a global container, but helped me more than once. Especially to avoid memory leaks and to ensure clean destruction of the whole hierarchy of interdependent objects.

Instead of typedef int node_id_t one can also use struct node_id_t { int id; }; and overload conversion operators to simplify node id lookups.

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