在STL列表中存储的每个项中存储对容器对象的引用的最有效方法
Most efficient way to store reference to container object in each item stored in STL list
假设我有这个基本设置:
#include <list>
struct Linker
{
Linker* to;
//some Linker specific stuff
};
struct Holder
{
std::list<Linker> links;
//some Holder specific stuff
//If I access the "to" variable in a Linker, I want to be able to access the data of the Holder that contains the Linker
};
存储在指向其他对象的列表中的简单对象,在这种情况下是相同类型的。当我访问链接器中的to
并获取另一个链接器时,我希望能够弄清楚其他链接器在哪个Holder中,并访问该链接器的数据。
在阅读了Will的回答后,我应该明确指出,我并没有试图模拟另一个列表。在实际实现中,并非Holder列表中的每一项都是Linker,我仍然需要通过列表访问所有内容(使用特定于订单的迭代)。但这个列表可以处理这个问题,所以没关系。我需要在Holder类的列表结构之上的不同列表/持有者中的项目之间进行一定程度的零星链接。
最好的方法是什么?我曾考虑在每个Linker中放置Holder引用或指针,但假设我想将像Linker这样的结构与容器的数据分开(有时在没有容器的其他上下文中使用它们,希望在没有容器信息的情况下在外部构建,然后让Holder使用添加函数来设置该信息,等等)。
我考虑过使用std::pair和Holder引用或指针作为另一种类型,或者将Linker扩展到类似HeldLinker的信息类型。也考虑过将类似的东西用于比std::pair:更具体的变量名
template<typename R, typename O> struct refwrap
{
R& ref;
O obj;
refwrap(R& ref, const O& obj) : ref(ref), obj(obj) {}
};
在所有这些情况下,Linker* to
和std::list<Linker> links
都会被修改为使用适当的类(std::pair、HeldLinker、refwrap等)。然而,似乎所有这些"解决方案"都会导致这样的功能:
void Holder::addlink(const Linker& link)
{
//wrap link into whatever will hold a Holder reference/pointer
//add to links list
}
复制传入的链接对象两次:在创建任何类型的包装器对象时,然后在将该包装器添加到std::list对象时再次复制。不执行任何这些包装方法都会将其限制为单个副本。有没有一种方法可以让我的蛋糕也吃,有一个必要的副本来添加,同时让Holder包装Linker对象,这样它们的引用也包含它们所在的Holder对象?或者,在完成同样的事情的同时,我是否可以为Linker使用一些更好的"寻址"方案来不符合这种范式?
最好,它是一个容易扩展的东西,所以如果我要添加这个:
struct HolderHolder
{
std::list<Holder> holders;
};
它建立了一种类似于Linker和Holder的关系,这可以在没有真正疯狂的类型名称的情况下完成。对于HolderHolderHolder等,
您想要在对象中存储对对象的引用的最有效方法吗?
最有效的方法是使用指针。它可能是4或8个字节,并且可能不会影响结构中下一项的对齐,因此可以。
您可以通过使用查找所有者对象的数字来保存字节,但这实际上可能不会在结构分配中保存实际字节,只是引入了填充。
设置指针需要一个内存字写入。目标可能与初始化期间正在执行的其他写入相邻;即使在严格的循环中,它也不太可能影响性能。
使用stl::list
的另一种选择是将列表节点本身放入数据结构中。
这在高性能环境中很常见,例如内核。以下是对Linux内核的描述。
通过在结构中放置下一个(可能还有上一个)指针(或对它们进行异或运算以节省空间),不需要单独的内存分配。
这意味着列表中的对象一次只能在一个列表中,但您的to
字段无论如何都意味着这一点,因此这不会约束您。
你可以有一个约定,头部实际上是拥有的对象;这显然需要O(n)来发现,但也许你只需要偶尔发现to
?
总结一下:
- 您可以通过根本不使用
stl::list
来节省内存,而只在节点本身中使用next
(和prev
,或者可能对它们进行XOR) - 可以使用保存的空间显式添加
to
字段 - 或者你可以有一个约定,列表的头实际上是所有者
- 如何使用 stl 容器有效地存储对象?(即根据其字段的值进行搜索)
- 线程上下文上的静态存储对象优化
- OOP - 存储对象和服务接口
- 为什么存储对象地址在缓冲区中会导致内存泄漏并删除它们
- 是否保证在销毁所有线程本地存储对象后销毁全局对象
- 使用列表存储对象
- 在c++中存储一个对象或不存储对象的首选方式是什么
- 更好的是:存储对象与存储指针
- 应用程序使用QMAP存储对象时停止响应
- 使用堆栈存储对象
- 如何在 std::map 中存储"对象类型"?
- 我应该如何存储对象
- 在 c++ 中存储对象的最佳策略是什么,确保名称唯一并能够在以后有效地检索它们
- 用于存储对象列表的最佳标准类
- 在C++中存储对象地址的数据结构
- 函子如何维护/存储对象的状态
- 我如何定义一个向量,并用C++在其中存储对象
- 存储对象以备将来使用(在重新启动程序时)
- C++/JNI-存储对象(jobject)在向量和数组中发生意外更改,C++或JNI问题
- 在多个容器中存储对象的最佳实践