C ++中的灵活成员数组

时间:2017-08-15 22:42:04

标签: c++ arrays

我需要什么(但在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上有几个解决这个问题的方法,但毕竟我没有弄清楚哪一个是正确的。

1 个答案:

答案 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;
}