更新
请查看Robert Knight的回答!他使用了C++11,但比这个方法更加简洁...
原始回答
这个可怕的hack怎么样:
namespace priv {
#define PRIVATE_STATICMEM(_A_) \
template <size_t size> \
struct StaticMem<size,_A_> { \
__declspec(align(_A_)) char data[size]; \
void *operator new(size_t parSize) { \
return _aligned_malloc(parSize,_A_); \
} \
void operator delete(void *ptr) { \
return _aligned_free(ptr); \
} \
};
template <size_t size, size_t align> struct StaticMem {};
template <size_t size> struct StaticMem<size,1> {char data[size];};
PRIVATE_STATICMEM(2)
PRIVATE_STATICMEM(4)
PRIVATE_STATICMEM(8)
PRIVATE_STATICMEM(16)
PRIVATE_STATICMEM(32)
PRIVATE_STATICMEM(64)
PRIVATE_STATICMEM(128)
PRIVATE_STATICMEM(256)
PRIVATE_STATICMEM(512)
PRIVATE_STATICMEM(1024)
PRIVATE_STATICMEM(2048)
PRIVATE_STATICMEM(4096)
PRIVATE_STATICMEM(8192)
}
template <typename T, size_t size> struct StaticMem : public priv::StaticMem<sizeof(T)*size,__alignof(T)> {
T *unhack() {return (T*)this;}
T &unhack(size_t idx) {return *(T*)(data+idx*sizeof(T));}
const T &unhack() const {return *(const T*)this;}
const T &unhack(size_t idx) const {return *(const T*)(data+idx*sizeof(T));}
StaticMem() {}
StaticMem(const T &init) {unhack()=init;}
};
看起来有点吓人,但你只需要在一些隐藏的头文件中使用它一次。然后你可以按照以下方式使用它:
StaticMem<T,N> array; //allocate an uninitialized array of size N for type T
array.data //this is a raw char array
array.unhack() //this is a reference to first T object in the array
array.unhack(5) //reference to 5th T object in the array
StaticMem<T,N> array;
可以出现在代码中,也可以作为某个更大类的成员(这就是我使用此技巧的方式),并且在堆上分配时也应该正确地表现。
错误修复:
示例的第6行:char data[_A_]
已更正为 char data[size]