我想使用并将“Handles”存储到对象缓冲区中的数据以减少分配开销。句柄只是带有对象的数组的索引。但是我需要检测重新分配后的使用情况,因为这可能很容易发生。常见的方法似乎是使用位字段。然而,这导致了两个问题:
我需要什么:
我得到了什么:
template<class T_HandleDef, typename T_Storage = uint32_t>
struct Handle
{
typedef T_HandleDef HandleDef;
typedef T_Storage Storage;
Handle(): handle_(0){}
private:
const T_Storage handle_;
};
template<unsigned T_numIndexBits = 16, typename T_Tag = void>
struct HandleDef{
static const unsigned numIndexBits = T_numIndexBits;
};
template<class T_Handle>
struct HandleAccessor{
typedef typename T_Handle::Storage Storage;
typedef typename T_Handle::HandleDef HandleDef;
static const unsigned numIndexBits = HandleDef::numIndexBits;
static const unsigned numMagicBits = sizeof(Storage) * 8 - numIndexBits;
/// "Magic" struct that splits the handle into values
union HandleData{
struct
{
Storage index : numIndexBits;
Storage magic : numMagicBits;
};
T_Handle handle;
};
};
用法例如:
typedef Handle<HandleDef<24> > FooHandle;
FooHandle Create(unsigned idx, unsigned m){
HandleAccessor<FooHandle>::HandleData data;
data.idx = idx;
data.magic = m;
return data.handle;
}
我的目标是尽可能保持手柄不透明,添加一个布尔检查,但没有别的。句柄的用户不应该对它做任何事情,而是传递它。
所遇到的问题:
T_Handle
替换为Storage
,然后将“ctor”添加到“存储处理”handle_
存储到文件中并从可能的不同字节序机器加载,并且index
和magic
是否正确?我想我可以存储包含Storage
'endian-correct'并获得正确的值, IF 两个成员占据正好一半的空间(2个短片在一个uint)但我总是想要更多的空间对于指数而不是魔术值。注意:已经有关于位域和联合的问题。总结:
handle = (magic << numIndexBits) | index
并将其保存/加载为二进制(无结束转换)缺少BigEndian计算机进行测试。注意:没有C ++ 11,但允许加速。
答案 0 :(得分:1)
答案非常简单(基于另一个问题,我忘记了@Jeremy Friesner的链接和评论):
由于“数字”已经是C ++中的抽象,当变量在CPU寄存器中时(当它用于任何计算时),可以确保始终具有相同的位表示。此外,C ++中的位移定义在一种与字节无关的方式。这意味着x << 1
总是等于x * 2
(因此也就是大端)
只有一次获得endianess问题是保存到文件,通过网络发送/ recv或以不同方式从内存访问它(例如通过指针......)
这里不能使用C ++位域,因为不能100%确定“条目”的顺序。如果Bitfield容器允许以“数字”访问数据,那么它可能没问题。
Savest(仍然)使用位移,在这种情况下非常简单(只有2个值)在存储/序列化期间,必须以与字节序无关的方式存储数字。