在各种类型的对象之间存储许多关系1:1:去耦和高性能

jav*_*ver 13 c++ database one-to-one relationship c++14

我有300多个班级.它们在某些方面有关系.

为简单起见,所有关系均为1:1.
这是一个示例图.

在此输入图像描述 (在实际情况中,大约有50个关系对.)

注意:对于某些情况,某些关系可能不存在.
例如,某些hen与任何内容无关food.

注2:没有链接=从不,例如每个egg都与任何相关cage.
永远不会添加/删除/查询这种关系.

题:

如何优雅地存储它们之间的关系?
我的所有4个想法(下面)似乎都有缺点.

是一个相关的问题,但是1:N只有1个关系.

我糟糕的解决方案

这些是半伪代码.

版本1直接

我的第一个想法是互相添加指针.

Chick.h: -

class Egg;
class Food;
class Chick{  Egg* egg; Food* food;}
Run Code Online (Sandbox Code Playgroud)

Hen.h: -

class Egg; class Cage; class Food;
class Hen{ Egg* egg; Cage* cage; Food* food;}
Run Code Online (Sandbox Code Playgroud)

添加/删除关系和查询非常便宜,例如: -

int main(){
    Hen* hen;    ...    Egg* egg=hen->egg;
}
Run Code Online (Sandbox Code Playgroud)

它运作良好,但随着我的程序的增长,我想要将它们分离.
粗略地说,Hen.h不应该包含单词Egg,反之亦然.

有很多想法,但似乎都没有.
我将展示每个解决方案的简短片段,然后总结问题末尾的利弊.

版本2哈希映射

使用std::unordered_map.
它成为我程序的瓶颈.(在发布模式下配置)

class Egg{}; class Hen{};  //empty (nice)
.....
int main(){
    std::unordered_map<Hen*,Egg*> henToEgg;
    std::unordered_map<Egg*,Hen*> eggToHen;
    ....
    Hen* hen;    ...    Egg* egg=henToEgg[hen];
}
Run Code Online (Sandbox Code Playgroud)

版本3中介 - 单一

将每个关系存储在每个实体的单个大调解器中.
为空插槽浪费了大量内存(例如EgghenFood_hen插槽).每个实体中的
总浪费= type-of-relation-pair*2*4个字节(如果以32位运行).

class Mediator {
    Egg* eggHen_egg=nullptr;
    Hen* eggHen_hen=nullptr;
    Hen* henFood_hen=nullptr;
    Food* henFood_food=nullptr;
    //... no of line = relation * 2
};
class Base{public: Mediator m;};
class Egg : public Base{};  //empty (nice)
class Hen : public Base{}; 
int main(){
     Hen* hen;    ...    Egg* egg=hen->eggHen_egg;
}
Run Code Online (Sandbox Code Playgroud)

版本4中介阵列(类似于3)

尝试标准化 - 高度灵活性.

class Mediator {
    Base* ptrLeft[5];
    Base* ptrRight[5];
};
class Base{public: Mediator m;};
class Egg : public Base{};  //empty (nice)
class Hen : public Base{}; 
int main(){
     enum RELA_X{RELA_HEN_EGG,RELA_HEN_CAGE,RELA_EGG_CHICK, .... };
     Hen* hen;    ...    
     Egg* egg=hen->m.ptrRight[RELA_HEN_EGG]; 
     //^ get right of "hen-egg" === get "egg" from "hen"
     //^ can be encapsulated for more awesome calling
}
Run Code Online (Sandbox Code Playgroud)

优点缺点

格林(+)很好.红色(-)很糟糕. 在此输入图像描述

编辑: 我正在使用Entity-Component进行60fps游戏.
它是一个持久性数据库:用于游戏整个生命周期的单个实例.

编辑2:所有的关系都是弱关系而不是一个一个强大的std::unique_ptr所有权.(感谢沃尔特)

  • 一个hen 一个cage.
    有些hens不在cage,有些cages是空的.
  • 一个chick 来自一个egg.
    然而,有些chicks人并非来自任何人egg(他们只是从天而降),
    有些eggs人没有幸运地成为chick.
  • A hen和a chick 正在吃一块(可能是相同的)盘子food.
    有些food盘子刚准备好但没有送达.

Edit3:为每个对象分配一个整数id可能是个好主意.
(感谢Oliv,ahoxha和Simone Cifani)

Edit4 ::不需要提供可编译的代码,只需要一个必不可少的部分/概念就足够了.

Out*_*und 1

这个问题没有也不可能有好的答案,因为你的算法未知。一般来说,您希望数据具有局部性,而间接总是破坏它的一种方法。

如果您有一个适用于母鸡的算法,您希望它们尽可能紧密地打包,并且最好在内存中呈线性,以获得最大的缓存命中率。

如果您的算法需要处理母鸡和鸡蛋之间的关系。他们需要是本地人。这不能通过将它们保存为母鸡中的指针来实现,但您需要一个包含所有母鸡 <-> 鸡蛋关系的数组。

你看,这很大程度上取决于你打算做什么。如果你真的想获得高绩效,你就必须防止深度间接。您尝试解析的每个指针都可能会破坏缓存行。如果你的CPU只是追着他们走,性能会很低。