void* AlignedMemory::allocate(size_t size, size_t alignment) { assert(0 < alignment && alignment <= 128 && Bitwise::isPO2(alignment)); unsigned char* p = new unsigned char[size + alignment]; size_t offset = alignment - (size_t(p) & (alignment-1)); unsigned char* result = p + offset; result[-1] = (unsigned char)offset; return result; }
该函数是这样的,因为要对内存按2的n次方对齐,在unsigned char* p = new unsigned char[size + alignment]; 这一句先申请了内存,但所得到的指针p可能不是内存对齐的,如按4字节对齐的话,内存地址只能是0x00000000,0x00000004,0x00000008等, 但如果分配到的p是0x00000001这个地址时怎么办,这时要通过加一个偏移值来使地址对齐,偏移值是这样算的, size_t offset = alignment - (size_t(p) & (alignment-1));其中( (size_t(p) & (alignment-1))等价于把p的值对alignment求余, 这就是size_t offset = alignment - size_t(p) %(alignment);对0x00000001这个地址来说:offset = 4 - (0x00000001 % 4) = 3; 0x00000001 + 3 = 0x00000004, 这样内存地址就对齐了,至于result[-1] = (unsigned char)offset; 因为1<=OFFSET<=3所以可以空一个字节也就是一个char出来存储result 最后的一行代码将result[-1]存放offset值的作用,是为了在释放时正确算回p的位置. void AlignedMemory::deallocate(void* p) { if (p) { unsigned char* mem = (unsigned char*)p; mem = mem - mem[-1];//算回原分配指针位置 delete [] mem; } }