C++ 跨对象树共享数据而不使用静态成员的策略
我需要在多态对象树的多个实例之间共享数据,但我需要共享数据为“每棵树”,因此在基类中使用静态类成员并不是一个真正的选项 我不想用指向共享数据的额外成员指针“覆盖”每个实例,因此我当前的方法(考虑到我使用树)是将共享数据作为树根节点的成员,并且每个对共享数据的访问都通过一个间接链,这取决于“树全局”通过的特定节点的深度访问数据 由于在某些情况下,共享数据将被非常频繁地访问(每秒数百万次…至少这是预期的),我想知道是否有一些设计模式可以帮助我避免间接访问根节点,同时仍然不会给对象的足迹带来额外的膨胀 虽然可以将根节点指针“缓存”为本地指针,例如访问共享数据的紧密循环,但在许多情况下,功能将沿树节点级联,甚至在过程中切换树,因此缓存根节点指针仅适用于狭窄的上下文C++ 跨对象树共享数据而不使用静态成员的策略,c++,c,design-patterns,tree,shared-data,C++,C,Design Patterns,Tree,Shared Data,我需要在多态对象树的多个实例之间共享数据,但我需要共享数据为“每棵树”,因此在基类中使用静态类成员并不是一个真正的选项 我不想用指向共享数据的额外成员指针“覆盖”每个实例,因此我当前的方法(考虑到我使用树)是将共享数据作为树根节点的成员,并且每个对共享数据的访问都通过一个间接链,这取决于“树全局”通过的特定节点的深度访问数据 由于在某些情况下,共享数据将被非常频繁地访问(每秒数百万次…至少这是预期的),我想知道是否有一些设计模式可以帮助我避免间接访问根节点,同时仍然不会给对象的足迹带来额外的膨胀
-
注意到静态成员的引用并没有限制实现的范围到C++,我也添加了C标记,因为在这点上我对任何想法都有开放性。
template<class Data>
struct internal_tree {
Data d;
std::unique_ptr<internal_tree> left;
std::unique_ptr<internal_tree> right;
};
template<class Data>
struct flyweight_tree {
private:
internal_tree* internal = nullptr;
internal_tree* root = internal;
flyweight_tree(internal_tree* t, internal_tree* r):internal(t),root(r) {}
public:
flyweight_tree() {}
flyweight_tree(internal_tree* r):internal(r) {}
flyweight_tree left() const { return { internal->left.get(), root }; }
flyweight_tree right() const { return { internal->right.get(), root }; }
};
模板
结构内部树{
数据d;
std::唯一左上角;
std::唯一的ptr权限;
};
模板
结构flyweight_树{
私人:
内部树*internal=nullptr;
内部树*根=内部;
flyweight_树(内部_树*t,内部_树*r):内部(t),根(r){}
公众:
flyweight_树(){}
flyweight_树(内部_树*r):内部(r){}
flyweight_tree left()常量{return{internal->left.get(),root};}
flyweight_tree right()const{return{internal->right.get(),root};}
};
现在,我们实际的内部_树
数据结构没有存储指向根的指针。使用它的代码通过flyweight_树
访问它,该树存储指向根的指针,但指向根的指针只存储在访问点,而不是长期存储
如果您想要一个父级
,您甚至可以将其实现为飞锤,其中飞锤树
存储指向父级的指针的std::vector
(而不是根
)。这在树节点中节省了另一堆内存(没有指向父节点的指针,但是每个使用它的人都可以获得父节点,因为他们通过flyweight\u树使用它)
我们可以在internal_树
中实现大部分工作,其中它将flyweight_树
存储的信息作为参数,或者我们可以在flyweight_树
中实现大部分树逻辑,并将internal_树
保留为紧凑的“长期存储”结构。我能想到的可能性有:
- 如果根的数量有限,则将偏移量(例如在uint8_t中)存储到具有根的静态数组。例如,如果您只有5-10个根,则无需为每个节点存储高达64位的数据
- 为什么不在自己的进程中运行每个“树”(在操作系统级别)?这样,每个根目录都可以存储为静态数据并全局访问
- 如果可以绑定节点数,可能可以使用特殊的分配器:首先在给定内存边界的开头分配根,例如0x0010000、0x002000等。。。然后通过对每个节点进行简单的减法/位移位来检索根的地址?但您必须能够确保可以在每个树的内存区域内分配所有节点
目标不是隐藏复杂性,而是减少内存占用。为了几个字节的共享数据而保留数百万个指针实在是太大的浪费了…@user3735658当然。因此,我减少了内存占用(通过不存储指向根的指针)。相反,每个方法都采用“指向根的指针”。然后,由于将指针传递给根容易出错且复杂,所以我们使用flyweight模式降低了复杂性。你需要一个飞锤模式的例子吗?