我需要什么(但在C ++中):
struct Element{
bool deleted;
T value;
}
struct Chunk{
Chunk* prev;
// other data
Element elements[]; // C99 flexible array member!
static make(std::size_t capacity){
Chunk *chunk = static_cast<Chunk *>(std::malloc(sizeof(Chunk) + sizeof(Element) * capacity));
// init data
return chunk;
}
}
但是C ++没有'灵活的数组成员'。所以我做了这样的事情:
struct Element{
bool deleted;
T value;
}
struct alignas(Element) Chunk{ // Chunk is always POD
Chunk* prev;
// other data
Element *elements() {
return static_cast<Element *>(static_cast<void *>(
reinterpret_cast<unsigned char *>(this) + sizeof(Chunk)
));
}
static make(std::size_t capacity){
Chunk *chunk = static_cast<Chunk *>(std::malloc(sizeof(Chunk) + sizeof(Element) * capacity));
// init data
// DO NOT INIT elements here. Will be placement newed' later.
return chunk;
}
}
问题是 - 这是正确的吗?或者这会导致UB吗?它是否正确对齐?这比Element elements[1]
技巧好吗?
P.S。在stackoverflow上有几个解决这个问题的方法,但毕竟我没有弄清楚哪一个是正确的。
答案 0 :(得分:1)
我最终得到了这个解决方案:
template<class Header, class T>
class FlexibleMemberArray {
struct alignas(T) AlignedHeader : Header{};
Header* self(){
return static_cast<Header*>(this);
}
protected:
static Header* make(const int capacity) {
Header *chunk = static_cast<Header *>(std::malloc(sizeof(AlignedHeader) + sizeof(T) * capacity));
return chunk;
}
inline T *elements() {
return static_cast<T *>(static_cast<void *>(reinterpret_cast<unsigned char *>(self()) +
sizeof(AlignedHeader)));
}
};
可以用作:
struct Chunk : public FlexibleMemberArray<Chunk, int>{
int capacity;
static void* operator new(std::size_t sz, int capacity) {
Chunk* self = make(capacity);
self->capacity = capacity;
return self;
}
using FlexibleMemberArray::elements;
};
int main() {
std::unique_ptr<Chunk> chunk {new (30) Chunk};
for(int i=0;i<chunk->capacity;i++){
chunk->elements()[i] = i;
}
for(int i=0;i<chunk->capacity;i++){
std::cout << chunk->elements()[i] << std::endl;
}
return 0;
}