我正在用 C++ 编写一个共享库,并且(主要是教育性的)目标是让库完成的每一点堆分配都生活在一个连续的块中,在库的特定部分初始化时分配。我在开始时用一个实现了这一点malloc
,它实现了两个堆栈(一个大且不可弹出用于持久内存,一个具有额外的机器作为辅助运行时堆栈)和一个用于半持久数据的二进制伙伴系统。
鉴于这种自我强加的约束,在这变成 XY 情况之前,我将描述我要解决的问题。我的图书馆有这些项目,可以有一些属性、结构,比如A
和B
. 我有更多类似 ECS 的数据扁平化,而不是具有单独继承的 OO 方法。项目只是 id,我记账谁在单独的数组中拥有每个属性。所以,如果我有 5 个项目,也许 {1, 3, 4, 5} 有属性 A 而 {2, 3, 4} 有属性 B,代码可能看起来像:
struct A;
struct B;
int whoHasA[] = {1, 3, 4, 5, 0};
A propertyA[] = {A1, A3, A4, A5, A::null()};
int whoHasB[] = {2, 3, 4, 0};
B propertyB[] = {B2, B3, B4, B::null()};
这些数组都可以按照我的约束进行分配,通过给它们一个固定的大小并通过空终止来“动态地”改变程序相关的大小,如数组中所示(我意识到这只是稀疏的临时实现数组。我喜欢它,因为我知道编写程序时的大小)。现在,我的库需要的功能如下。我希望我的用户能够创建项目实例(最多为某个最大数量),并在事后添加/删除属性。
为此,我希望我的用户按名称而不是繁琐的 id 来引用项目。然后我需要在我的 API 中公开以下函数
void CreateItem(const char* name); //Store item name in a registry
void GiveProperty(const char* name, A property); //Append item's id to whoHasA and property to propertyA
void GiveProperty(const char* name, B property); //Append item's id to whoHasB and property to propertyB
我需要将名称存储在内存中,因为我想向脚本(当前是 Lua)公开类似的功能。想到的解决方案是某种关联映射,将字符串作为键,将项目 ID 作为值。std::unordered_map
由于它在地图本身和std::string
作为键的动态分配,我一直在避免。目前我正在做的就是定义一个const char** itemNames
写入CreateItem
的对象,并通过它们进行基本的线性搜索,char
在char
每个条目上进行比较。我没有对它进行基准测试,也不认为它会特别麻烦,但我问这个问题是希望有一个更优雅的解决方案,它更适合并且(理论上)更有效。