我正在编写一个系统,该系统具有大量需要保留在内存中的冗余数据,并且可以在尽可能小的延迟下访问。 (未压缩,数据保证吸收1GB内存,最低)。
我想到的一种方法是创建一个如下容器类:
class Chunk{
public:
Chunk(){ ... };
~Chunk() { /*carefully delete elements according to mask*/ };
getElement(int index);
setElement(int index);
private:
unsigned char mask; // on bit == data is not-redundant, array is 8x8, 64 elements
union{
Uint32 redundant; // all 8 elements are this value if mask bit == 0
Uint32 * ptr; // pointer to 8 allocated elements if mask bit == 1
}array[8];
};
我的问题是,使用联盟在Uint32
主要指针和Uint32*
指针之间切换是否有任何看不见的后果?
答案 0 :(得分:3)
这种方法对所有C ++实现都应该是安全的。
但请注意,如果您了解平台的内存对齐要求,则可能比此更好。特别是,如果您知道内存分配对齐到2个字节或更多(许多平台使用8或16个字节),您可以使用指针的低位作为标志:
class Chunk {
//...
uintptr_t ptr;
};
// In your get function:
if ( (ptr & 1) == 0 ) {
return ((uint32_t *)ptr)[index];
} else {
return *((uint32_t *)(ptr & ~(uintptr_t)0);
}
您可以通过使用自定义分配方法(使用placement new)进一步减少空间使用量,并将指针放在类之后,在单个内存分配中(即,您将为Chunk
分配空间,并且掩码或数组,ptr
之后立即指向Chunk
。或者,如果您知道大多数数据的位数较低,则可以直接使用ptr
字段作为填充值:
} else {
return ptr & ~(uintptr_t)0;
}
如果它是通常未使用的高位,则会有一点位移位:
} else {
return ptr >> 1;
}
请注意tagging pointers的这种方法是不可移植的。只有在可以确保内存分配正确对齐的情况下才是安全的。在大多数桌面操作系统上,这不会是一个问题 - malloc已经确保了一定程度的对齐;在Unix上,使用posix_memalign
可以绝对肯定。但是,如果您可以为您的平台获得这样的保证,这种方法可能非常有效。
答案 1 :(得分:2)
如果空间有限,你可能会浪费记忆力。它将为最大元素分配足够的空间,在这种情况下,指针最多可以是64位。
如果坚持使用32位体系结构,则不应该遇到强制转换问题。